diff options
Diffstat (limited to 'src/Authoring/Studio/_Win')
113 files changed, 23993 insertions, 0 deletions
diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.cpp b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp new file mode 100644 index 00000000..533a5601 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/AboutDlg.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "qtAuthoring-config.h" +#include "StudioDefs.h" +#include "Strings.h" +#include "StringLoader.h" + +//============================================================================== +// Includes +//============================================================================== +#include "AboutDlg.h" +#include "ui_AboutDlg.h" +#include "ProductInfo.h" +#include "HotKeys.h" +#include "Preferences.h" +#include "StudioPreferences.h" + +#include <QMouseEvent> +#include <QPainter> +#include <QTimer> + +//============================================================================== +// Constants +//============================================================================== +const int TIMER_RESIZEABOUT = 6; +const int TIMER_FADEOUT = 7; + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +CAboutDlg::CAboutDlg(QWidget* parent) + : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint) + , m_ScrollingCreditsFlag(false) + , m_ui(new Ui::AboutDlg) +{ + m_ui->setupUi(this); + m_IconRect = m_ui->icon->pixmap()->rect(); + setFixedSize(size()); + + m_Font = QFont(CStudioPreferences::GetFontFaceName()); + m_Font.setPointSizeF(7.8); + m_Font = QFont(CStudioPreferences::GetFontFaceName()); + m_Font.setPointSizeF(8.8); + + m_Color_Background = CStudioPreferences::GetDarkBaseColor(); + m_Color_Text = CStudioPreferences::GetNormalColor(); + + OnInitDialog(); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +CAboutDlg::~CAboutDlg() +{ +} + +//============================================================================== +/** + * Handles the painting of the icon in the About Box. + * All additional painting (text, etc) occurs by default by MFC. + */ +//============================================================================== +void CAboutDlg::paintEvent(QPaintEvent* event) +{ + Q_UNUSED(event); + if (!m_ScrollingCreditsFlag) { + DrawFadeRect(); + } +} + +//============================================================================== +/** + * Completes the construction of the About Box. + * Stores the product version in the member variable associated with the static + * text box in the dialog template. This version information comes from the + * VersionNumber.h file in $/Studio/Build. + * @return Returns TRUE always. + */ +void CAboutDlg::OnInitDialog() +{ + // Set the Studio version + m_ProductVersionStr.Format( + ::LoadResourceString(IDS_UIC_STUDIO_VERSION), + static_cast<const wchar_t *>(CStudioPreferences::GetVersionString())); + + // Set the copyright string + m_CopyrightStr.Format(::LoadResourceString(IDS_ABOUT_COPYRIGHT), + static_cast<const wchar_t *>(Q3DStudio::CString(STUDIO_COPYRIGHT_YEAR))); + + // Set the credit strings + m_Credit1Str.Format(::LoadResourceString(IDS_ABOUT_PAINTLIB_CREDIT)); +#ifdef QT_3DSTUDIO_FBX + m_Credit2Str.Format(::LoadResourceString(IDS_ABOUT_FBX_CREDIT)); +#endif + +#ifdef STUDIOSTORYNUM + m_ProductVersionStr += " (Story #"; + m_ProductVersionStr += STUDIOSTORYNUM; + m_ProductVersionStr += ")"; +#endif + +#ifdef BETA + // Add "beta" to the Studio version if necessary + m_ProductVersionStr += " BETA"; +#endif + + // Add link to Web site + Q3DStudio::CString theURL(::LoadResourceString(IDS_HELP_VISIT_QT)); + + m_ui->m_WebSite->setText(QString("<a href=\"%1\">%2</a>").arg(theURL.toQString(), theURL.toQString())); + m_ui->m_WebSite->setToolTip(::LoadResourceString(IDS_WEBSITELINK).toQString()); + m_ui->m_WebSite->setOpenExternalLinks(true); + + // Add link to support email address + Q3DStudio::CString theEmail; + Q3DStudio::CString theEmailSansProtocol; + + theEmail = ::LoadResourceString(IDS_SUPPORTEMAIL); + theEmailSansProtocol = "support@qt.io"; + + m_ui->m_Email->setText(QString("<a href=\"%1\">%2</a>").arg(theEmail.toQString(), theEmailSansProtocol.toQString())); + m_ui->m_Email->setToolTip(::LoadResourceString(IDS_SUPPORTEMAIL_TEXT).toQString()); + m_ui->m_Email->setOpenExternalLinks(true); + + // Set the fonts + m_ui->m_Copyright->setFont(m_Font); + m_ui->m_Credit1->setFont(m_Font); + m_ui->m_Credit2->setFont(m_Font); + m_ui->m_WebSiteLabel->setFont(m_Font); + m_ui->m_WebSite->setFont(m_Font); + m_ui->m_EmailLabel->setFont(m_Font); + m_ui->m_Email->setFont(m_Font); + + // Make the font bold for version numbers + m_ui->m_ProductVersion->setFont(m_BoldFont); + + // Create brush for background color + m_Brush = QBrush(m_Color_Background); + + m_ui->m_ProductVersion->setText(m_ProductVersionStr.toQString()); + m_ui->m_Copyright->setText(m_CopyrightStr.toQString()); + m_ui->m_Credit1->setText(m_Credit1Str.toQString()); + m_ui->m_Credit2->setText(m_Credit2Str.toQString()); + + // Hide the email link until we have a valid one. + m_ui->m_EmailLabel->setVisible(false); + m_ui->m_Email->setVisible(false); +} + +//============================================================================== +/** + * Handles the WM_LBUTTONDBLCLK message + * Check to see if the mouse is within the Qt logo and the control key is pressed. + * If so, begin the transition to show the detailed credits. + */ +void CAboutDlg::mouseDoubleClickEvent(QMouseEvent* event) +{ + // If the mouse's left button is double-clicked in the Qt logo while the control key is + // pressed... + if (m_IconRect.contains(event->pos())) { + // if ( CHotKeys::IsKeyDown( VK_CONTROL ) ) + //{ + // Start the transition to display the scrolling credits + // Crashing... this->BeginCreditsTransition(); + //} + } + + QDialog::mouseDoubleClickEvent(event); +} + +//============================================================================== +/** + * BeginCreditsTransition: Begin the transition from the About box to the scrolling credits. + */ +void CAboutDlg::BeginCreditsTransition() +{ + m_ScrollingCreditsFlag = TRUE; + + // Hide all controls + for (QWidget* w : findChildren<QWidget*>()) + w->setVisible(false); + + // Invalidate the window + update(); + + // Set the resizing timer + QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout); +} + +//============================================================================== +/** + * Resize the about box height until the Client area is square. + */ +void CAboutDlg::ResizeAbout() +{ + bool retriggerResizeAbout = true; + + QRect theClientRect = rect(); + bool theRightSize = false; + + // this is just a sizing stuff to show some transition on size + if (theClientRect.height() < theClientRect.width()) { + theClientRect.setBottom(theClientRect.bottom() + 5); + if (theClientRect.bottom() >= theClientRect.width()) { + theRightSize = true; + theClientRect.setBottom(theClientRect.width()); + retriggerResizeAbout = false; + } + } else { + theClientRect.setRight(theClientRect.right() + 5); + if (theClientRect.right() >= theClientRect.height()) { + theRightSize = true; + theClientRect.setRight(theClientRect.height()); + retriggerResizeAbout = false; + } + } + + if (parentWidget()) + theClientRect.moveCenter(parentWidget()->geometry().center()); + else + theClientRect.moveTopLeft(geometry().topLeft()); + + setGeometry(theClientRect); + + if (theRightSize) { + QColor the3DColor; + short theColorValue; + + m_CreditsRect = rect().adjusted(3, 3, -3, -3); + + the3DColor = palette().color(QPalette::Base); + theColorValue = + (short)((the3DColor.red() + the3DColor.green() + the3DColor.blue()) / 3); + + m_ColorFade = RGB(theColorValue, theColorValue, theColorValue); + + QTimer::singleShot(50, this, &CAboutDlg::FadeOut); + } + + if (retriggerResizeAbout) { + QTimer::singleShot(50, this, &CAboutDlg::ResizeAbout); + } +} + +//============================================================================== +/** + * Fade out a rectangle in the client area, from the background 3D color to black. + */ +void CAboutDlg::FadeOut() +{ + update(); + + // Continue fading to black + if (m_ColorFade != Qt::black) { + short theColorValue; + + theColorValue = (short)(m_ColorFade.red() - 10); + + if (theColorValue < 0) + theColorValue = 0; + + m_ColorFade = qRgb(theColorValue, theColorValue, theColorValue); + QTimer::singleShot(50, this, &CAboutDlg::FadeOut); + } +} + +//============================================================================== +/** + * DrawFadeRect: Draw the faded rectangle as we transition to the scrolling credits. + */ +void CAboutDlg::DrawFadeRect() +{ + QPainter painter(this); + painter.fillRect(m_CreditsRect, m_ColorFade); +} + +void CAboutDlg::OnStnClickedAboutboxProdver() +{ + // TODO: Add your control notification handler code here +} diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.h b/src/Authoring/Studio/_Win/Application/AboutDlg.h new file mode 100644 index 00000000..244e7192 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/AboutDlg.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_ABOUT_DLG_H +#define INCLUDED_ABOUT_DLG_H 1 + +#pragma once + +#include <QDialog> + +#include "UICString.h" + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { + class AboutDlg; +} +QT_END_NAMESPACE + +class CAboutDlg : public QDialog +{ + Q_OBJECT +public: + CAboutDlg(QWidget* parent = nullptr); + ~CAboutDlg(); + + // Implementation +protected: + bool m_ScrollingCreditsFlag = false; // TRUE if credits are being scrolled + QRect m_IconRect; // bounding rectangle to display the about image + QRect m_CreditsRect; // bounding rectangle for the scrolling credits + QColor m_ColorFade; // fade-out color to fade to the credits window + QFont m_Font; // Font for text + QFont m_BoldFont; // Font for Studio/Client version number + + QColor m_Color_Background; + QColor m_Color_Text; + QBrush m_Brush; + + void BeginCreditsTransition(); + + void DrawFadeRect(); + + void FadeOut(); + + void ResizeAbout(); + + //{{AFX_MSG(CAboutDlg) + void paintEvent(QPaintEvent* event) override; + void OnInitDialog(); + + void mouseDoubleClickEvent(QMouseEvent* event) override; + + Q3DStudio::CString m_ProductVersionStr; + Q3DStudio::CString m_CopyrightStr; + Q3DStudio::CString m_Credit1Str; + Q3DStudio::CString m_Credit2Str; + +public: + void OnStnClickedAboutboxProdver(); + +private: + QScopedPointer<Ui::AboutDlg> m_ui; +}; + +#endif // INCLUDED_ABOUT_DLG_H diff --git a/src/Authoring/Studio/_Win/Application/AboutDlg.ui b/src/Authoring/Studio/_Win/Application/AboutDlg.ui new file mode 100644 index 00000000..a5fe3433 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/AboutDlg.ui @@ -0,0 +1,180 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>AboutDlg</class> + <widget class="QDialog" name="AboutDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>502</width> + <height>483</height> + </rect> + </property> + <property name="windowTitle"> + <string>About Qt 3D Studio</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QLabel" name="icon"> + <property name="pixmap"> + <pixmap resource="../../MainFrm.qrc">:/res/About Icon.bmp</pixmap> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="widget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="Line" name="m_Line1"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_ProductVersion"> + <property name="text"> + <string><studio version goes here></string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_Copyright"> + <property name="text"> + <string><Copyright goes here></string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_Credit1"> + <property name="text"> + <string><Credit 1 goes here></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_Credit2"> + <property name="text"> + <string><Credit 2 goes here></string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="Line" name="m_Line2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_WebSiteLabel"> + <property name="text"> + <string>Web site:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_WebSite"> + <property name="text"> + <string><Link to support site here></string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_EmailLabel"> + <property name="text"> + <string>Support email:</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="m_Email"> + <property name="text"> + <string><Link to support email here></string> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + </item> + </layout> + </widget> + <resources> + <include location="../../MainFrm.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>AboutDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>AboutDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.cpp b/src/Authoring/Studio/_Win/Application/BaseLink.cpp new file mode 100644 index 00000000..5e7b4775 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/BaseLink.cpp @@ -0,0 +1,252 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +#ifdef _DEBUG +//#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//============================================================================== +// Includes +//============================================================================== + +#include "BaseLink.h" +#include "Resource.h" +#include "StudioColors.h" + +// The IDC_HAND should be defined in WinUser.h if the WINVER is 0x5000 or greater +#ifndef IDC_HAND +#define IDC_HAND MAKEINTRESOURCE(32649) +#endif + +///////////////////////////////////////////////////////////////////////////// +// CBaseLink class + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CBaseLink::CBaseLink() +{ + m_bCapture = FALSE; +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CBaseLink::~CBaseLink() +{ +} + +//============================================================================== +// Message Map +//============================================================================== + +BEGIN_MESSAGE_MAP(CBaseLink, CWnd) +//{{AFX_MSG_MAP(CBaseLink) +ON_WM_PAINT() +ON_WM_SETCURSOR() +ON_WM_MOUSEMOVE() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +/** + * ShowTextLink: Shows the text link. + * + * @param None + */ +//============================================================================== +void CBaseLink::ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat, + bool inUnderlineText) +{ + if (IsWindow(m_hWnd)) { + CRect theRect; + CFont *theFont; + CFont *theOldFont = nullptr; + CDC *theDC; + CDC theMemDC; + CString theTextBuffer; + + // Set up the link font. + theFont = GetFont(); + if (theFont != nullptr) { + LOGFONT theLogFont; + + theFont->GetLogFont(&theLogFont); + + // Turn on the underline style... + if (inUnderlineText) + theLogFont.lfUnderline = TRUE; + else + theLogFont.lfUnderline = FALSE; + + theFont = new CFont(); + + if (theFont != nullptr) { + theFont->CreateFontIndirect(&theLogFont); + } + } + + GetClientRect(&theRect); + GetWindowText(theTextBuffer); + + theDC = GetDC(); + + theDC->SetTextColor(inTextColor); + theDC->SetBkColor(inBackColor); + + // Fill the background. + theDC->FillSolidRect(&theRect, inBackColor); + + // Set the font and draw the text. + if (theFont != nullptr) { + theOldFont = (CFont *)theDC->SelectObject(theFont); + } + theDC->DrawText(theTextBuffer, &theRect, inTextFormat); + + if (theOldFont != nullptr) { + theDC->SelectObject(theOldFont); + } + ReleaseDC(theDC); + + if (theFont != nullptr) { + theFont->DeleteObject(); + delete theFont; + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// CBaseLink message handlers + +//============================================================================== +/** + * OnPaint - Handler for the WM_PAINT message + * + * Draw the control. + * + * @param None + */ +//============================================================================== +void CBaseLink::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + if (IsWindowEnabled()) + this->ShowLink(); +} + +//============================================================================== +/** + * OnSetCursor + * + * Handle the WM_SETCURSOR message. + * + * @param inWnd Pointer to the parent CWnd object. + * @param inHitTest Specifies the hit-test area code. The hit test determines the + *cursor�s location. + * @param inMessage Specifies the mouse message number. + */ +//============================================================================== +BOOL CBaseLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage) +{ + UNREFERENCED_PARAMETER(inWnd); + UNREFERENCED_PARAMETER(inHitTest); + UNREFERENCED_PARAMETER(inMessage); + + SetCursor(LoadCursor(nullptr, IDC_HAND)); + + return TRUE; +} + +//============================================================================== +/** + * OnMouseMove + * + * Windows callback handler for the WM_MOUSEMOVE message + * + * @param inFlags Flags for the left button up message + * @param inPoint Point where the left button was last moved (client coordinates) + */ +//============================================================================== +void CBaseLink::OnMouseMove(UINT inFlags, CPoint inPoint) +{ + UNREFERENCED_PARAMETER(inFlags); + UNREFERENCED_PARAMETER(inPoint); + + if (IsWindowEnabled()) { + + if (!m_bCapture) { + SetCursor(LoadCursor(nullptr, IDC_HAND)); + SetCapture(); + + m_bCapture = TRUE; + this->ShowLink(); + } else { + // Already captured... + if (!this->IsMouseOverLink()) { + m_bCapture = FALSE; + ReleaseCapture(); + + this->ShowLink(); + } + } + } +} + +//============================================================================== +/** + * IsMouseOverLink: Determine if the mouse is over the control. + * + * @param None + * + * @return true if the mouse is over the control. + */ +//============================================================================== +bool CBaseLink::IsMouseOverLink() +{ + POINT theMousePos; + RECT theWndRect; + + ::GetCursorPos(&theMousePos); + GetWindowRect(&theWndRect); + + return PtInRect(&theWndRect, theMousePos) ? true : false; +} diff --git a/src/Authoring/Studio/_Win/Application/BaseLink.h b/src/Authoring/Studio/_Win/Application/BaseLink.h new file mode 100644 index 00000000..4d89a155 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/BaseLink.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _BASELINK_H_ +#define _BASELINK_H_ + +///////////////////////////////////////////////////////////////////////////// +// CBaseLink window + +class CBaseLink : public CWnd +{ + // Construction +public: + CBaseLink(); + + // Attributes +public: + // Operations +public: +protected: + bool m_bCapture; + + virtual bool IsMouseOverLink(); + virtual void ShowLink() = 0; + virtual void ShowTextLink(COLORREF inTextColor, COLORREF inBackColor, UINT inTextFormat, + bool inUnderlineText); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CBaseLink) + //}}AFX_VIRTUAL + + // Implementation +public: + virtual ~CBaseLink(); + + // Generated message map functions +protected: + //{{AFX_MSG(CBaseLink) + virtual afx_msg void OnPaint(); + virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message); + virtual afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/Authoring/Studio/_Win/Application/MsgRouter.cpp b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp new file mode 100644 index 00000000..4ce57cc8 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/MsgRouter.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "MsgRouter.h" +#include "StudioConst.h" +#include "Core.h" +#include "Doc.h" +#include "Views.h" + +#include <QCoreApplication> + +static std::unique_ptr<CMsgRouter> static_theInstance; + +//============================================================================== +/** + * Constructor + */ +CMsgRouter::CMsgRouter() +{ + qApp->installEventFilter(this); + m_eventType = QEvent::registerEventType(); +} + +//============================================================================== +/** + * Destructor + */ +CMsgRouter::~CMsgRouter() +{ +} + +CMsgRouter *CMsgRouter::GetInstance() +{ + if (!static_theInstance) { + static_theInstance.reset(new CMsgRouter); + } + + return static_theInstance.get(); +} + +//============================================================================== +/** + * Send a command to be executed asynchronously. + */ +void CMsgRouter::SendCommand(CCmd *inCommand, CCore *inCore) +{ + SMessageData *theMsgData = new SMessageData(m_eventType); + theMsgData->Method = &CMsgRouter::OnCommand; + theMsgData->Data = inCommand; + theMsgData->Data2 = inCore; + + qApp->postEvent(qApp, theMsgData); +} + +bool CMsgRouter::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == m_eventType) { + SMessageData *theMsgData = reinterpret_cast<SMessageData *>(event); + (this->*(theMsgData->Method))(theMsgData); + return true; + } + + return false; +} + +//============================================================================== +/** + * Windows entry point for processing generic messages. + */ +void CMsgRouter::OnAsyncNotification(SMessageData *inMessageData) +{ + try { + CRoutedMessageBase *theRoutedMsg = static_cast<CRoutedMessageBase *>(inMessageData->Data); + if (theRoutedMsg) + theRoutedMsg->Notify(); + } catch (...) { + // Catch crashes in case the object is gone + } +} + +//============================================================================== +/** + * Main thread processing for processing command execution messages. + */ +void CMsgRouter::OnCommand(SMessageData *inMsgData) +{ + CCmd *theCommand = static_cast<CCmd *>(inMsgData->Data); + CCore *theCore = static_cast<CCore *>(inMsgData->Data2); + theCore->ExecuteCommand(theCommand, true); +} + + + +CMsgRouter::SMessageData::SMessageData(int eventType) : + QEvent(static_cast<QEvent::Type>(eventType)) +{ +} diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.cpp b/src/Authoring/Studio/_Win/Application/StudioApp.cpp new file mode 100644 index 00000000..fa160431 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/StudioApp.cpp @@ -0,0 +1,1835 @@ +/**************************************************************************** +** +** Copyright (C) 1999-2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +#ifdef _WIN32 +#pragma warning(disable : 4100) // unreferenced formal parameter +#endif +#include "StudioApp.h" +#include "SubPresentationsDlg.h" +#include "UICStateApplication.h" + +#include <QtGui/qsurfaceformat.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qurl.h> + +int main(int argc, char *argv[]) +{ + // to enable QOpenGLWidget to work on macOS, we must set the default + // QSurfaceFormat before QApplication is created. Otherwise context-sharing + // fails and QOpenGLWidget breaks. + + // fortunately, we know which OpenGL version we can use on macOS, so we + // can simply hard-code it here. +#if defined(Q_OS_MACOS) + QSurfaceFormat openGL33Format; + openGL33Format.setRenderableType(QSurfaceFormat::OpenGL); + openGL33Format.setProfile(QSurfaceFormat::CoreProfile); + openGL33Format.setMajorVersion(3); + openGL33Format.setMinorVersion(3); + openGL33Format.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(openGL33Format); +#endif + + // init runtime static resources + Q_INIT_RESOURCE(res); + + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication guiApp(argc, argv); + // Load and apply stylesheet for the application + QFile styleFile(":/style.qss"); + styleFile.open(QFile::ReadOnly); + guiApp.setStyleSheet(styleFile.readAll()); + g_StudioApp.InitInstance(argc, argv); + return g_StudioApp.Run(); +} + +//============================================================================== +// Includes +//============================================================================== +#include "Exceptions.h" +#include "IOLibraryException.h" +#include "Strings.h" +#include "MainFrm.h" +#include "AboutDlg.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "StackOps.h" +#include "Views.h" +#endif +#include "StringLoader.h" +#include "Doc.h" +#include "Dialogs.h" +#include "Dispatch.h" +#include "StartupDlg.h" +#include "RecentItems.h" +#include "StudioPreferences.h" +#include "MsgRouter.h" +#include "SplashView.h" +#include "Views.h" +#include "UICLog.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "WinUtils.h" +#include "CrashDlg.h" +#endif +#include "UICFile.h" +#include "UICFileTools.h" +#include "ITickTock.h" +#include "IStudioRenderer.h" +#include "IDocumentEditor.h" +#include "StudioUtils.h" + +#ifdef KDAB_TEMPORARILY_REMOVED +#include "IObjectReferenceHelper.h" +#endif +#include "ClientDataModelBridge.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "CommonConstants.h" +#include "IOLibraryException.h" + +#ifdef _DEBUG +#include "UICMemoryLeak.h" +#endif +#include "UICDMErrors.h" + +#include <iostream> +#include <fstream> +#include <stdio.h> +#include <io.h> +#include <fcntl.h> +#endif +#include <string.h> + +#include <QApplication> +#include <QSettings> + +#ifdef KDAB_TEMPORARILY_REMOVED +#include "..\Build\versionnumber.h" + +#include "UICDESKey.h" // g_DESKey +#endif + +#include "Core.h" +#include "HotKeys.h" +#include "StudioTutorialWidget.h" +#include "GuideInspectable.h" +#include "UICDMStudioSystem.h" +#include "UICDMInspectable.h" +#include "UICDMSlides.h" +#include "UICDMMaterialInspectable.h" +#include "UICDMSceneInspectable.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "UICDMAnimation.h" +#include "UICDMDataCore.h" +#include "SlideControl.h" +#endif +#include "IDirectoryWatchingSystem.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "ITickTock.h" +#include "UICFileTools.h" +#include "foundation/Qt3DSLogging.h" + +#endif +#ifdef USE_LICENSE_HANDLER +#include "licensehandler.h" +#endif + +CStudioApp g_StudioApp; +long g_UICErrorCode = 0; + +using namespace Q3DStudio; + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +char g_DumpPath[MAX_PATH] = { 0 }; + +#ifndef WIN32 +namespace qt3ds +{ +void NVAssert(const char *exp, const char *file, int line, bool *igonore) +{ + qFatal("NVAssertion thrown %s(%d): %s", file, line, exp); +} +} +#endif + +//============================================================================= +/** + * Constructor + */ +CStudioApp::CStudioApp() +#ifdef KDAB_TEMPORARILY_REMOVED + , m_SplashPalette(nullptr) + , m_OldHelpFilePath(nullptr) + , m_UnitTestResults(0) + , m_IsSilent(false) + , m_Core(NULL) + , m_Views(NULL) + , m_Dialogs(NULL) + , m_ManipulationMode(StudioManipulationModes::Local) + , m_PlaybackTime(0) + , m_pGdiToken(0) + , m_AuthorZoom(false) +#endif + : m_ToolMode(STUDIO_TOOLMODE_MOVE) + , m_SelectMode(STUDIO_SELECTMODE_GROUP) + , m_welcomeShownThisSession(false) + , m_goStraightToWelcomeFileDialog(false) + , m_tutorialPage(0) +{ +#ifdef KDAB_TEMPORARILY_REMOVED +#ifdef _DEBUG + AfxEnableMemoryTracking(TRUE); + CMemoryLeak::SetXMLFileName("StudioMemoryLeaks.xml"); + CMemoryLeak::SetShowDialogOnExit(false); +#endif // _DEBUG + g_DumpPath[0] = 0; +#endif +} + +//============================================================================= +/** + * Destructor + */ +CStudioApp::~CStudioApp() +{ + // Do not call PerformShutdown from here as the C has already been shutdown (!!) +} + +void CStudioApp::PerformShutdown() +{ + m_DirectoryWatcherTicker = std::shared_ptr<UICDM::ISignalConnection>(); + + // Dispatch un-registration + if (m_Core) { + m_Core->GetDispatch()->RemoveAppStatusListener(this); + m_Core->GetDispatch()->RemoveCoreAsynchronousEventListener(this); + qCInfo(qt3ds::TRACE_INFO) << "Studio exiting successfully"; + } + + if (m_Renderer) { + m_Renderer->Close(); + m_Renderer = std::shared_ptr<Q3DStudio::IStudioRenderer>(); + } + + // No need to delete m_SplashPalette. You should not call delete on CFrameWnds, + // you should call DestroyWindow( ) instead. See the MSDN. + // delete m_SplashPalette; +#ifdef KDAB_TEMPORARILY_REMOVED + delete m_Views; + m_Views = nullptr; + delete m_Dialogs; + m_Dialogs = nullptr; + delete m_Core; + m_Core = nullptr; +#endif + + CStringLoader::UnloadStrings(); + + // Get rid of the temp files + CUICFile::ClearCurrentTempCache(); + + qApp->exit(); +} + +//============================================================================= +/** + * Entry location for the creation of this application. + * This creates the all the views, then returns if everything + * was successful. + */ +BOOL CStudioApp::InitInstance(int argc, char* argv[]) +{ + QApplication::setOrganizationName("The Qt Company"); + QApplication::setOrganizationDomain("qt.io"); + QApplication::setApplicationName("Qt 3D Studio"); + QApplication::setApplicationVersion( + QString::fromWCharArray(CStudioPreferences::GetVersionString().c_str())); + + qCInfo(qt3ds::TRACE_INFO) << "Studio: " << QApplication::applicationFilePath(); + + // Load the strings used by the app gui + // This needs to occur prior to parsing command line arguments + // since access to the strings are required by some of the cases + CUICFile theResDir(CString::fromQString(resourcePath() + QStringLiteral("/strings"))); + CStringLoader::LoadStrings(theResDir); + qCInfo(qt3ds::TRACE_INFO) << "Version: " + << CStudioPreferences::GetVersionString().GetCharStar(); + + std::vector<wchar_t*> wargv; + wargv.resize(argc); + for (int i = 0; i < argc; ++i) { + QString arg = argv[i]; + wargv[i] = new wchar_t[arg.size() + 1]; + wargv[i][arg.size()] = L'\0'; + arg.toWCharArray(wargv[i]); + } + + // Parse the command line so we know what's up + m_CmdLineParser.ParseArguments(argc, &(wargv[0])); + + // Silent mode indicates that Studio will be operated in a muted "no-GUI" mode + m_IsSilent = m_CmdLineParser.IsSilent(); + + // If we're just running unit tests, return before creating windows/MFC controls + if (m_CmdLineParser.IsRunUnitTests()) { + { + RunCmdLineTests(m_CmdLineParser.GetFilename()); + return FALSE; // return false so we bail from loading the app + } + } + +#ifdef KDAB_TEMPORARILY_REMOVED + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need + // Change the registry key under which our settings are stored + Q3DStudio::CString theRegistryKey = + ::LoadResourceString(IDS_UICOMPOSER_PALETTE_SETTINGS_REGISTRY_KEY); + SetRegistryKey(theRegistryKey); +#endif + + CFilePath thePreferencesPath = CFilePath::GetUserApplicationDirectory(); + thePreferencesPath = CFilePath::CombineBaseAndRelative( + thePreferencesPath, CFilePath(L"UIComposer\\Preferences.setting")); + CPreferences::SetPreferencesFile(thePreferencesPath); + +#ifdef KDAB_TEMPORARILY_REMOVED + // Set up the path to the help file + InitHelpSystem(); +#endif + + CStudioPreferences::LoadPreferences(); + + m_Dialogs = new CDialogs(!m_IsSilent); + + if (!m_IsSilent) { + // Show the splash screen + m_SplashPalette = new CSplashView(); + m_SplashPalette->setWindowTitle(::LoadResourceString(IDS_PROJNAME).toQString()); + m_SplashPalette->show(); + + m_Views = new CViews(this); + } + + // All custom icons (PNGs) are drawn using Gdiplus so that transparency are handled. + // note that gdiplus.dll are included with WinXP ( previous OS versions require the gdi + // redistributables to be installed and unless + // support for those OS becomes a priority, we assume Studio is run minimally on a XP machine ) +#ifdef KDAB_TEMPORARILY_REMOVED + Gdiplus::GdiplusStartup(&m_pGdiToken, &m_gdiplusStartupInput, nullptr); // gdi+ init +#endif + + m_Core = new CCore(); + GetRenderer(); + m_Core->GetDoc()->SetSceneGraph(m_Renderer); + + // Dispatch registration + m_Core->GetDispatch()->AddAppStatusListener(this); + m_Core->GetDispatch()->AddCoreAsynchronousEventListener(this); + + return TRUE; +} + +//============================================================================= +/** + * Exit location for the destruction of this application. + * @return 0 on success; -1 on failure + */ +int CStudioApp::ExitInstance() +{ + int theResult = -1; + +#ifdef KDAB_TEMPORARILY_REMOVED + // CWinApp::InitInstance returns 1(TRUE) on success; 0(FALSE) on failure + if (CWinApp::InitInstance() == TRUE) + theResult = 0; + + if (m_CmdLineParser.IsRunUnitTests() && 0 == m_UnitTestResults) + theResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure + +#ifdef _DEBUG + // If appears that MFC takes over dumping memory leaks on exit + // this is the only way I've been able to turn it off. + + // Turn off dumping CRT memory leaks + ::_CrtSetReportMode(_CRT_WARN, 0); + ::_CrtSetReportMode(_CRT_ERROR, 0); + ::_CrtSetReportMode(_CRT_ASSERT, 0); +#endif + + // Make sure any GDI resources have been cleaned up + CResourceCache::GetInstance()->Clear(); + // Called in conjuction with Gdiplus::GdiplusStartup + Gdiplus::GdiplusShutdown(m_pGdiToken); +#endif + + return theResult; +} + +//============================================================================= +/** + * Command handler to display the about dialog. + */ +void CStudioApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.exec(); +} + +#ifdef KDAB_TEMPORARILY_REMOVED +//============================================================================= +/** + * Overrides registry access member functions, direct settings to a XML file + */ +UINT CStudioApp::GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault) +{ + QT3DS_ASSERT(lpszSection != nullptr); + QT3DS_ASSERT(lpszEntry != nullptr); + + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection); + return CPreferences::GetUserPreferences(theSubKeyName).GetLongValue(lpszEntry, nDefault); +} +BOOL CStudioApp::WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue) +{ + QT3DS_ASSERT(lpszSection != nullptr); + QT3DS_ASSERT(lpszEntry != nullptr); + + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection); + CPreferences::GetUserPreferences(theSubKeyName).SetLongValue(lpszEntry, nValue); + return TRUE; +} +::CString CStudioApp::GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, + LPCTSTR lpszDefault /* = nullptr */) +{ + QT3DS_ASSERT(lpszSection != nullptr); + QT3DS_ASSERT(lpszEntry != nullptr); + + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection); + return CPreferences::GetUserPreferences(theSubKeyName).GetStringValue(lpszEntry, lpszDefault); +} +BOOL CStudioApp::WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue) +{ + QT3DS_ASSERT(lpszSection != nullptr); + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%s\\%s\\%s", PALETTE_KEY, PALETTE_SUBKEY, lpszSection); + + if (lpszEntry == nullptr) // delete whole section + { + CPreferences::GetUserPreferences(theSubKeyName).Clear(); + } else if (lpszValue == nullptr) { + CPreferences::GetUserPreferences(theSubKeyName).RemoveKey(lpszEntry); + } else { + CPreferences::GetUserPreferences(theSubKeyName).SetStringValue(lpszEntry, lpszValue); + } + return TRUE; +} +#endif + +//============================================================================= +/** + * Main application execution loop. + * The application's main thread stays in this until the app exits. + * @return 0 on success; -1 on failure + */ +int CStudioApp::Run() +{ + int theRetVal = -1; + +#ifdef USE_LICENSE_HANDLER + LicenseHandler lh; + if (!lh.handleLicense()) + return theRetVal; +#endif + + try { + UIC_LOGSTART; + +#ifdef KDAB_TEMPORARILY_REMOVED + // Set the crash handler for all unhandled exceptions. + CStackOps::SetCrashProc(&StudioUnhandledCrashHandler); + CStackOps::RegisterCrashHandler(); + CStackOps::EnableCrashingOnCrashes(); +#endif + + CCmdLineParser::EExecutionMode theMode = m_CmdLineParser.PopExecutionMode(); + if (CCmdLineParser::END_OF_CMDS == theMode) + theMode = CCmdLineParser::NORMAL; + + for (; CCmdLineParser::END_OF_CMDS != theMode; + theMode = m_CmdLineParser.PopExecutionMode()) { + // This just switches the execution mode of the app and starts it in the correct state. + switch (theMode) { + case CCmdLineParser::TEST_CMD_LINE: + theRetVal = RunSystemTests(m_CmdLineParser.GetFilename()); + break; + case CCmdLineParser::OPEN_FILE: + theRetVal = OpenAndRunApplication(m_CmdLineParser.GetFilename()); + break; + default: + theRetVal = BlankRunApplication(); + break; + } + + // if any operations returned a bad value, stop following operations + if (-1 == theRetVal) + break; + } + PerformShutdown(); + + UIC_LOGSTOP; + } catch (CUICExceptionClass &inException) { + g_UICErrorCode = inException.GetErrorCode(); + throw; + } catch (UICDM::UICDMError &uicdmError) { + Q_UNUSED(uicdmError); + +#ifdef KDAB_TEMPORARILY_REMOVED + EXCEPTION_POINTERS *pExPtrs; + CStackOps::GetExceptionPointers(1, &pExPtrs); + StudioUnhandledCrashHandler(pExPtrs); +#endif + exit(1); + } catch (...) { + throw; + } + + return theRetVal; +} + +bool CStudioApp::HandleWelcomeRes(int res, bool recursive) +{ + int theReturn = true; + switch (res) { + case StudioTutorialWidget::createNewResult: { + std::pair<CUICFile, bool> theFile = m_Dialogs-> + GetNewDocumentChoice(Q3DStudio::CString(".")); + if (theFile.first.GetPath() != "") { + m_Core->OnNewDocument(theFile.first, theFile.second); + theReturn = true; + m_welcomeShownThisSession = true; + } else { + // User Cancels the dialog. Show the welcome screen. + if (recursive) { + m_welcomeShownThisSession = false; + m_goStraightToWelcomeFileDialog = true; + theReturn = ShowStartupDialog(); + } else { + theReturn = false; + } + } + } break; + + case StudioTutorialWidget::openSampleResult: { + // Try three options: + // - open a specific example directory with .uip file in it + // - failing that, show the main example root dir + // - failing all previous, show Qt3DStudio dir + Q3DStudio::CFilePath filePath; + + filePath = CUICFile::GetApplicationDirectory().GetPath()+ + Q3DStudio::CString("../examples/qmldynamickeyframes/presentation"); + + if (!filePath.Exists()) { + filePath = CUICFile::GetApplicationDirectory().GetPath()+ + Q3DStudio::CString("../examples"); + } + if (!filePath.Exists()) { + filePath = CUICFile::GetApplicationDirectory().GetPath()+ + Q3DStudio::CString("."); + } + + CUICFile theFile = m_Dialogs->GetFileOpenChoice(filePath); + + if (theFile.GetPath() != "") { + OnLoadDocument(theFile); + theReturn = true; + m_welcomeShownThisSession = true; + } else { + // User Cancels the dialog. Show the welcome screen. + if (recursive) { + m_welcomeShownThisSession = false; + m_goStraightToWelcomeFileDialog = true; + theReturn = ShowStartupDialog(); + } else { + theReturn = false; + } + } + } break; + + default: + ASSERT(false); // Should not reach this block. + theReturn = false; + break; + } + return theReturn; +} + +//============================================================================= +/** + * Show startup dialog and perform necessary action such as create new doc or load doc. + * Return false if user requests to exit + */ +bool CStudioApp::ShowStartupDialog() +{ + int welcomeRes = QDialog::Rejected; + bool theReturn = true; + + if (!m_welcomeShownThisSession){ + m_welcomeShownThisSession = true; + + bool show = false; + QSettings settings; + + if (!settings.contains("showWelcomeScreen")) { + settings.setValue("showWelcomeScreen", 1); + show = true; + } else { + // if we are returning to welcome dialog page after canceling + // file dialog, do not care about settings but always show + // welcome + show = settings.value("showWelcomeScreen").toBool() + || m_goStraightToWelcomeFileDialog; + } + + if (show) { + StudioTutorialWidget tutorial(m_goStraightToWelcomeFileDialog); + welcomeRes = tutorial.exec(); + } + } + + // show the usual startup dialog only if user rejected tutorial + // ( = did not open samples or create new project) + if (welcomeRes == QDialog::Rejected) { + CStartupDlg theStartupDlg; + + // Populate recent items + Q3DStudio::CFilePath theMostRecentDirectory; + if (m_Views) { + CRecentItems *theRecentItems = m_Views->GetMainFrame()->GetRecentItems(); + for (long theIndex = 0; theIndex < theRecentItems->GetItemCount(); ++theIndex) { + if (theIndex == 0) { + theMostRecentDirectory = + Q3DStudio::CFilePath(theRecentItems->GetItem(0).GetAbsolutePath()) + .GetDirectory(); + } + theStartupDlg.AddRecentItem(theRecentItems->GetItem(theIndex)); + } + } + + theStartupDlg.exec(); + CStartupDlg::EStartupChoice theChoice = theStartupDlg.GetChoice(); + + switch (theChoice) { + case CStartupDlg::EStartupChoice_Exit: + theReturn = false; + break; + + case CStartupDlg::EStartupChoice_NewDoc: { + std::pair<CUICFile, bool> theFile = m_Dialogs-> + GetNewDocumentChoice(theMostRecentDirectory); + if (theFile.first.GetPath() != "") { + m_Core->OnNewDocument(theFile.first, theFile.second); + theReturn = true; + } else { + // User Cancels the dialog. Show startup dialog again. + theReturn = ShowStartupDialog(); + } + } break; + + case CStartupDlg::EStartupChoice_OpenDoc: { + CUICFile theFile = m_Dialogs->GetFileOpenChoice(theMostRecentDirectory); + if (theFile.GetPath() != "") { + OnLoadDocument(theFile); + theReturn = true; + } else { + // User Cancels the dialog. Show startup dialog again. + theReturn = ShowStartupDialog(); + } + } break; + + case CStartupDlg::EStartupChoice_OpenRecent: { + CUICFile theFile = theStartupDlg.GetRecentDoc(); + if (theFile.GetPath() != "") { + OnLoadDocument(theFile); + // throw SlideNotFound( L""); + theReturn = true; + } else { + // User Cancels the dialog. Show startup dialog again. + theReturn = ShowStartupDialog(); + } + } break; + + default: + ASSERT(false); // Should not reach this block. + theReturn = false; + break; + } + } else { // open sample or create new + theReturn = HandleWelcomeRes(welcomeRes, true); + } + return theReturn; +} + +//============================================================================= +/** + * Start the app. + */ +int CStudioApp::BlankRunApplication() +{ + InitCore(); + + if (ShowStartupDialog()) + return RunApplication(); + return -1; +} + +//============================================================================= +/** + * Run the unit tests specified on the command line then return. + * @param inTestPath input unit test path + * @return 0 on success; 1 on failure + */ +int CStudioApp::RunCmdLineTests(const Q3DStudio::CString &inTestPath) +{ + Q_UNUSED(inTestPath); + + return m_UnitTestResults; +} + +//============================================================================= +/** + * Run the system level tests specified on the command line then return. + * @param inTestPath + * @return 0 on success; -1 on failure + */ +int CStudioApp::RunSystemTests(const Q3DStudio::CString &inTestPath) +{ + int theSystemTestsResult = -1; + + Q_UNUSED(inTestPath); + + if (0 == m_UnitTestResults) + theSystemTestsResult = m_UnitTestResults; // unit tests return 0 on success; 1 on failure + + return theSystemTestsResult; +} + +//============================================================================= +/** + * Open the specified file and run the application. + * This will load the file then go into the standard app loop. + * On load with the -silent flag, this would force the application to exit on + * load failures. + * @return 0 on success; -1 on failure + */ +int CStudioApp::OpenAndRunApplication(const Q3DStudio::CString &inFilename) +{ + int theSuccess = -1; + InitCore(); + if (OnLoadDocument( + inFilename, + false)) // Load document. Upon failure, don't show startup dialog but exit immediately. + theSuccess = RunApplication(); + return theSuccess; +} + +//============================================================================= +/** + * This is the app execution loop, the main thread loops here until the app exits. + * @return 0 on success; -1 on failure + */ +int CStudioApp::RunApplication() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + BOOL bIdle = TRUE; + LONG lIdleCount = 0; + MSG theMessage; + + // CStackOps::RegisterCrashHandler( ); + + // acquire and dispatch messages until a WM_QUIT message is received. + for (;;) { + // phase1: check to see if we can do idle work + while (bIdle && !::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE)) { + // call OnIdle while in bIdle state + if (!OnIdle(lIdleCount++)) + bIdle = FALSE; // assume "no idle" state + } + + // phase2: pump messages while available + do { + try { + // Pump message, but quit on WM_QUIT + if (!PumpMessage()) + return ExitInstance(); + } catch (...) { + // Throw here so that any crash goes through the crash reporter + throw; + } + + // Reset "no idle" state after pumping "normal" message + if (IsIdleMessage(&theMessage)) { + bIdle = TRUE; + lIdleCount = 0; + } + } while (::PeekMessage(&theMessage, nullptr, nullptr, nullptr, PM_NOREMOVE)); + } +#endif + return qApp->exec(); +} + +//============================================================================= +/** + * Initialize the core and all the views. + */ +void CStudioApp::InitCore() +{ + // Initialize and cache the RenderSelector values for the first time, + // this way, subsequent attempts to instantiate a RenderSelector would circumvent the need + // for any extra (unneccesary) creation of render contexts which inadvertently cause exceptions + // to be thrown. + + m_Core->Initialize(); + + if (m_Views) { + m_Views->CreateViews(); + m_pMainWnd = m_Views->GetMainFrame(); + } else { + ASSERT(0); // No views? wha? + } + +#ifdef KDAB_TEMPORARILY_REMOVED + CMsgRouter::GetInstance()->SetMainframe(m_pMainWnd); +#endif + + // At this point, get rid of the splash screen, otherwise any errors dialog would be hidden + // behind. + // Could happen when this is directly activated due to a uip file being dbl-clicked or dragged + // into the executable. + if (m_SplashPalette) { + m_SplashPalette->deleteLater(); + m_SplashPalette = nullptr; + } + + RegisterGlobalKeyboardShortcuts(m_Core->GetHotKeys()); + m_Core->GetDispatch()->AddPresentationChangeListener(this); +} + +struct SIImportFailedHandler : public Q3DStudio::IImportFailedHandler +{ + CDialogs &m_Dialogs; + SIImportFailedHandler(CDialogs &dialogs) + : m_Dialogs(dialogs) + { + } + void DisplayImportFailed(const QString &inDocumentPath, + const QString &inDescription, bool inWarningsOnly) override + { + m_Dialogs.DisplayImportFailed(QUrl(inDocumentPath), inDescription, inWarningsOnly); + } +}; + +struct SIDeletingReferencedObjectHandler : public Q3DStudio::IDeletingReferencedObjectHandler +{ + CDialogs &m_Dialogs; + + SIDeletingReferencedObjectHandler(CDialogs &dialogs) + : m_Dialogs(dialogs) + { + } + + void DisplayMessageBox(const Q3DStudio::CString &inDescription) override + { + Q3DStudio::CString theTitle(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_TITLE)); + Q3DStudio::CString theFormat(::LoadResourceString(IDS_DELETE_OBJ_CONFIRM_MSG)); + Q3DStudio::CString theMessage; + theMessage.Format(theFormat, static_cast<const wchar_t *>(inDescription)); + + m_Dialogs.DisplayMessageBox(theTitle, theMessage, CUICMessageBox::ICON_WARNING, false); + } +}; + +void CStudioApp::SetupTimer(long inMessageId, QWidget *inWnd) +{ + m_TickTock = ITickTock::CreateTickTock(inMessageId, inWnd); + GetDirectoryWatchingSystem(); + m_Core->GetDoc()->SetDirectoryWatchingSystem(m_DirectoryWatchingSystem); + m_Core->GetDoc()->SetImportFailedHandler( + std::make_shared<SIImportFailedHandler>(std::ref(*GetDialogs()))); + m_Core->GetDoc()->SetDocMessageBoxHandler( + std::make_shared<SIDeletingReferencedObjectHandler>(std::ref(*GetDialogs()))); +} + +ITickTock &CStudioApp::GetTickTock() +{ + if (m_TickTock == nullptr) + throw std::runtime_error("Uninitialized TickTock"); + return *m_TickTock; +} + +Q3DStudio::IStudioRenderer &CStudioApp::GetRenderer() +{ + if (!m_Renderer) + m_Renderer = Q3DStudio::IStudioRenderer::CreateStudioRenderer(); + return *m_Renderer; +} + +void CStudioApp::ClearGuides() +{ + SCOPED_DOCUMENT_EDITOR(*m_Core->GetDoc(), QObject::tr("Clear Guides"))->ClearGuides(); +} + +void SendAsyncCommand(CDispatch &inDispatch, Q3DStudio::TCallbackFunc inFunc) +{ + inDispatch.FireOnAsynchronousCommand(inFunc); +} + +IDirectoryWatchingSystem &CStudioApp::GetDirectoryWatchingSystem() +{ + if (m_DirectoryWatchingSystem == nullptr) { + Q3DStudio::TCallbackCaller theCaller = + std::bind(SendAsyncCommand, std::ref(*m_Core->GetDispatch()), std::placeholders::_1); + m_DirectoryWatchingSystem = + IDirectoryWatchingSystem::CreateThreadedDirectoryWatchingSystem(theCaller); + } + return *m_DirectoryWatchingSystem; +} + +#ifdef KDAB_TEMPORARILY_REMOVED +bool s_testVar = true; +//============================================================================== +/** + * This gets called any time an unhandled exception is thrown anywhere in the + * application. + * + * @param pExPtrs a description of the exception. + * @return 0 if not handled, 1 if it was handled. + */ +void CStudioApp::StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs) +{ + TCHAR theTraceBuffer[4096]; + CCrashDlg theDlg; + Q3DStudio::CString errorMessage; + + CStackOps::GetExceptionStackTrace(theTraceBuffer, sizeof(theTraceBuffer), + pExPtrs->ContextRecord); + if (g_UICErrorCode != 0) { + // switch (g_UICErrorCode) + //{ + // default: + Q3DStudio::CString description; + description.Format(_UIC("Custom error 0x%X "), g_UICErrorCode); + errorMessage = CStackOps::GetExceptionDescription(description, pExPtrs); + // break; + //} + } else { + errorMessage = CStackOps::GetExceptionDescription(pExPtrs); + } + theDlg.SetStackTrace(theTraceBuffer); + qCCritical(qt3ds::INTERNAL_ERROR) << "Crash!" << theTraceBuffer; + // Attempt to save the current project (although this may crash). + CDoc &theDoc = *g_StudioApp.m_Core->GetDoc(); + CFilePath theFullPath = theDoc.GetDocumentPath().GetAbsolutePath(); + CFilePath theDir = theFullPath.GetDirectory(); + CFilePath theStem = theFullPath.GetFileStem(); + theStem.append(L"_Crash"); + // Attempt to open a dump file ideally next to the log file. + CFilePath theSaveFile; + { + TFilePtr theSaveFilePtr = + SFileTools::FindUniqueDestFile(theDir, theStem, CFilePath(L"uip")); + theSaveFile = theSaveFilePtr->m_Path; + } + theSaveFile.DeleteThisFile(); + theDoc.SaveDocument(CUICFile(theSaveFile)); + qCInfo(qt3ds::TRACE_INFO) << "Project successfully saved: " << theSaveFile.GetCharStar(); + + ::CString fileSaveLocationMessage; + fileSaveLocationMessage.Format(L"Project saved as %ls", + static_cast<const wchar_t *>(theSaveFile)); + + theDlg.SetErrorMessage(errorMessage); + theDlg.SetFilename(fileSaveLocationMessage); + theDlg.DoModal(); +} + +void CStudioApp::InitHelpSystem() +{ + Q3DStudio::CString theHelpFile = ::LoadResourceString(IDS_HELP_FILE_NAME); + + ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theOldHelpPath(m_pszHelpFilePath); + ATL::CStringT<TCHAR, StrTraitMFC<TCHAR>> theNewHelpPath; + + long theIndex = theOldHelpPath.ReverseFind('\\'); + theOldHelpPath.Delete(theIndex + 1, (theOldHelpPath.GetLength() - theIndex)); + theNewHelpPath = theOldHelpPath; + ::CString theMFCHelpFile(theHelpFile.GetMulti()); + theNewHelpPath += theMFCHelpFile; + + // Save the m_pszHelpFilePath variable so that CWinApp::SetCurrentHandles() + // in appinit.cpp can deallocate the memory it allocated, which causes a + // mmgr.h assert when we free it in here + m_OldHelpFilePath = const_cast<LPTSTR>(m_pszHelpFilePath); + + long theLength = theNewHelpPath.GetLength(); + m_pszHelpFilePath = new TCHAR[theLength + 1]; + ::lstrcpyn(const_cast<LPTSTR>(m_pszHelpFilePath), theNewHelpPath, theLength + 1); +} +#endif + +CCore *CStudioApp::GetCore() +{ + return m_Core; +} + +//============================================================================= +/** + * Get the view manager for this core to communicate to the views. + */ +CViews *CStudioApp::GetViews() +{ + return m_Views; +} + +//============================================================================= +/** + * Get the dialog manager for this core for displaying dialogs. + */ +CDialogs *CStudioApp::GetDialogs() +{ + return m_Dialogs; +} + +long CStudioApp::GetToolMode() +{ + return m_ToolMode; +} + +void CStudioApp::SetToolMode(long inToolMode) +{ + if (m_ToolMode != inToolMode) { + m_ToolMode = inToolMode; + m_Core->GetDispatch()->FireOnToolbarChange(); + } +} + +long CStudioApp::GetSelectMode() +{ + return m_SelectMode; +} + +void CStudioApp::SetSelectMode(long inSelectMode) +{ + if (m_SelectMode != inSelectMode) { + m_SelectMode = inSelectMode; + m_Core->GetDispatch()->FireOnToolbarChange(); + } +} + +StudioManipulationModes::Enum CStudioApp::GetMinpulationMode() const +{ + return m_ManipulationMode; +} +void CStudioApp::SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode) +{ + if (m_ManipulationMode != inManipulationMode) { + m_ManipulationMode = inManipulationMode; + m_Core->GetDispatch()->FireOnToolbarChange(); + } +} + +//============================================================================= +/** + * return true if undo is possible + */ +bool CStudioApp::CanUndo() +{ + return m_Core->GetCmdStack()->CanUndo(); +} + +//============================================================================= +/** + * return true if redo is possible + */ +bool CStudioApp::CanRedo() +{ + return m_Core->GetCmdStack()->CanRedo(); +} + +void CStudioApp::OnCopy() +{ + m_Core->GetDoc()->HandleCopy(); +} + +bool CStudioApp::CanCopy() +{ + return m_Core->GetDoc()->CanCopy(); +} + +//============================================================================= +/** + * Get a string describing the type of the copy operation that can be done. + * Precedence of copying is 1) Actions; 2) Keyframes; 3) Objects + */ +Q3DStudio::CString CStudioApp::GetCopyType() +{ + Q3DStudio::CString theCopyType; + + CDoc *theDoc = m_Core->GetDoc(); + if (theDoc->CanCopyAction()) + theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION); + else if (theDoc->CanCopyKeyframe()) + theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES); + else + theCopyType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT); + + return theCopyType; +} + +//============================================================================= +/** + * Cuts the selected object or keys + */ +void CStudioApp::OnCut() +{ + m_Core->GetDoc()->HandleCut(); +} + +bool CStudioApp::CanCut() +{ + return m_Core->GetDoc()->CanCut(); +} + +//============================================================================= +/** + * Paste keys from the copied list yo + */ +void CStudioApp::OnPaste() +{ + m_Core->GetDoc()->HandlePaste(); +} + +bool CStudioApp::CanPaste() +{ + return m_Core->GetDoc()->CanPaste(); +} + +//============================================================================= +/** + * Get a string describing the type of the paste operation that can be done. + * Precedence of paste is 1) Actions; 2) Object ; 3) Keyframes + */ +Q3DStudio::CString CStudioApp::GetPasteType() +{ + Q3DStudio::CString thePasteType; + + CDoc *theDoc = m_Core->GetDoc(); + if (theDoc->CanPasteAction()) + thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_ACTION); + else if (theDoc->CanPasteObject()) + thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_OBJECT); + else + thePasteType = ::LoadResourceString(IDS_MENU_COPYPASTE_TYPE_KEYFRAMES); + + return thePasteType; +} + +bool CStudioApp::CanChangeTimebarColor() +{ + bool theRetVal = true; + UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance(); + if (!theSelectedInstance.Valid() + || m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsSceneInstance( + theSelectedInstance)) + theRetVal = false; + + return theRetVal; +} + +//============================================================================= +/** + * Sets any changed keyframes on the selected object + */ +void CStudioApp::HandleSetChangedKeys() +{ + m_Core->GetDoc()->SetChangedKeyframes(); +} + +//============================================================================= +/** + * Deletes all selected keys + */ +void CStudioApp::DeleteSelectedKeys() +{ + m_Core->GetDoc()->DeleteSelectedKeys(); +} + +//============================================================================= +/** + * Handles the duplicate object command + */ +void CStudioApp::HandleDuplicateCommand() +{ + m_Core->GetDoc()->HandleDuplicateCommand(); +} + +//============================================================================= +/** + * return true if the selected object is duplicatable + */ +bool CStudioApp::CanDuplicateObject() +{ + // Get the currently selected object + UICDM::CUICDMInstanceHandle theSelectedInstance = m_Core->GetDoc()->GetSelectedInstance(); + +#ifdef KDAB_TEMPORARILY_REMOVED + // Check if the object can be duplicated + return m_Core->GetDoc()->GetStudioSystem()->GetClientDataModelBridge()->IsDuplicateable( + theSelectedInstance); +#endif + return false; +} + +//============================================================================== +/** + * Toggles the state of autoset keyframes. + */ +void CStudioApp::OnToggleAutosetKeyframes() +{ + SetAutosetKeyframes(!CStudioPreferences::IsAutosetKeyframesOn()); + + m_Core->GetDispatch()->FireOnToolbarChange(); +} + +//============================================================================== +/** + * Updates the preferences, and AnimationSystem. + */ +void CStudioApp::SetAutosetKeyframes(bool inFlag) +{ + CStudioPreferences::SetAutosetKeyframesOn(inFlag); + + m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe(inFlag); +} + +//============================================================================== +/** + * If the presentation is not currently playing, this function will make it + * start playing from the current position. The starting point of the playhead + * is saved so that it can be restored later. + */ +void CStudioApp::PlaybackPlay() +{ + CDoc *theDoc = m_Core->GetDoc(); + if (!theDoc->IsPlaying()) { + m_PlaybackTime = theDoc->GetCurrentViewTime(); + m_PlaybackOriginalSlide = theDoc->GetActiveSlide(); + theDoc->SetPlayMode(PLAYMODE_PLAY); + } +} + +//============================================================================== +/** + * If the presentation is currently playing, it is stopped. The playhead is + * left wherever it was stopped at (hence it's not restored). + */ +void CStudioApp::PlaybackStopNoRestore() +{ + m_Core->GetDoc()->SetPlayMode(PLAYMODE_STOP); +} + +//============================================================================== +/** + * Moves the playhead back to time zero. + */ +void CStudioApp::PlaybackRewind() +{ + CDoc *theDoc = m_Core->GetDoc(); + if (theDoc->IsPlaying()) { + theDoc->SetPlayMode(PLAYMODE_STOP, 0); + theDoc->SetPlayMode(PLAYMODE_PLAY); + } else { + m_Core->GetDoc()->NotifyTimeChanged(0); + } +} + +//============================================================================= +/** + * Performs a file revert. + * This will revert the doc to the last saved version. + */ +void CStudioApp::OnRevert() +{ + if (!m_Core->GetDoc()->IsModified() || m_Dialogs->ConfirmRevert()) { + CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath(); + OnLoadDocument(theCurrentDoc); + } +} + +//============================================================================= +/** + * Check to see if it is possible to perform a revert. + */ +bool CStudioApp::CanRevert() +{ + return m_Core->GetDoc()->IsModified() && m_Core->GetDoc()->GetDocumentPath().GetPath() != ""; +} + +//============================================================================== +/** + * Handles the recent list. + */ +void CStudioApp::OnFileOpenRecent(const CUICFile &inDocument) +{ + if (PerformSavePrompt()) + OnLoadDocument(inDocument); +} + +//============================================================================== +/** + * Called when closing the current doc, this prompts the user to save the doc. + * This will only prompt if the doc is modified, and if the user selects save + * then this will perform the save operation. + * @return true if the operation should continue, false if not. + */ +bool CStudioApp::PerformSavePrompt() +{ + if (m_Core->GetDoc()->IsModified()) { + CDialogs::ESavePromptResult theResult = m_Dialogs->PromptForSave(); + if (theResult == CDialogs::SAVE_FIRST) { + bool onSaveResult = OnSave(); + if (onSaveResult) + return true; + } else if (theResult == CDialogs::CONTINUE_NO_SAVE) + return true; + + return false; + } + return true; +} + +//============================================================================== +/** + * If the presentation is currently playing, it is stopped. The playhead is + * restored to the position found in m_PlaybackTime. + */ +void CStudioApp::PlaybackStop() +{ + CDoc *theDoc = m_Core->GetDoc(); + // change it back to the original slide first before restoring the original time + if (m_PlaybackOriginalSlide.Valid()) { + if (m_PlaybackOriginalSlide != theDoc->GetActiveSlide()) + theDoc->NotifyActiveSlideChanged(m_PlaybackOriginalSlide); + theDoc->SetPlayMode(PLAYMODE_STOP, m_PlaybackTime); + } + // Invalidate the playback original slide so we don't inadvertently trigger this code later. + m_PlaybackOriginalSlide = 0; +} + +//============================================================================= +/** + * Used for track wheel to do smooth tracking on mac, just scrolls the playhead. + */ +void CStudioApp::AdvanceTime() +{ + long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount(); + long theTime = + (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime; + m_Core->GetDoc()->NotifyTimeChanged(theTime); +} + +//============================================================================= +/** + * Used for track wheel to do smooth tracking on mac, just scrolls the playhead. + */ +void CStudioApp::ReduceTime() +{ + long theDeltaTime = CStudioPreferences::GetTimeAdvanceAmount(); + long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime; + m_Core->GetDoc()->NotifyTimeChanged(theTime); +} + +//============================================================================= +/** + * Used for track wheel to do smooth tracking on mac, just scrolls the playhead. + */ +void CStudioApp::AdvanceUltraBigTime() +{ + long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount(); + long theTime = + (m_Core->GetDoc()->GetCurrentViewTime() + theDeltaTime) / theDeltaTime * theDeltaTime; + m_Core->GetDoc()->NotifyTimeChanged(theTime); +} + +//============================================================================= +/** + * Used for track wheel to do smooth tracking on mac, just scrolls the playhead. + */ +void CStudioApp::ReduceUltraBigTime() +{ + long theDeltaTime = CStudioPreferences::GetBigTimeAdvanceAmount(); + long theTime = (m_Core->GetDoc()->GetCurrentViewTime() - 1) / theDeltaTime * theDeltaTime; + m_Core->GetDoc()->NotifyTimeChanged(theTime); +} + +//============================================================================== +/** + * If the presentation is currently playing, it is stopped. Otherwise, the + * presetation starts playing from its current position. Called when the user + * presses the Enter key. + */ +void CStudioApp::PlaybackToggle() +{ + // If the presentation is playing, stop it and leave the playhead where it is + if (m_Core->GetDoc()->IsPlaying()) + PlaybackStopNoRestore(); + // Otherwise, the presentation is stopped, so start it playing + else + PlaybackPlay(); +} + +CInspectableBase *CStudioApp::GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable) +{ + CInspectableBase *theInspectableBase = nullptr; + if (inSelectable.empty() == false) { + switch (inSelectable.getType()) { + case Q3DStudio::SelectedValueTypes::Slide: + theInspectableBase = new CUICDMInspectable( + *this, m_Core, inSelectable.getData<Q3DStudio::SSlideInstanceWrapper>().m_Instance); + break; + case Q3DStudio::SelectedValueTypes::MultipleInstances: + case Q3DStudio::SelectedValueTypes::Instance: { + + // We need to decide whether to display SlideInspectable or UICDMInspectable + // We display SlideInspectable if user selects a Scene or Component where the current + // active slide belongs, + // for example when user selects the Root in Timeline Palette + CDoc *theDoc = m_Core->GetDoc(); + UICDM::TInstanceHandleList theSelectedInstances = + theDoc->GetSelectedValue().GetSelectedInstances(); + UICDM::CUICDMInstanceHandle theSelectedInstance; + if (theSelectedInstances.size() == 1) + theSelectedInstance = theSelectedInstances[0]; + + if (m_Core->GetDoc()->GetDocumentReader().IsInstance(theSelectedInstance)) { + CClientDataModelBridge *theBridge = + theDoc->GetStudioSystem()->GetClientDataModelBridge(); + UICDM::CUICDMSlideHandle theCurrentActiveSlide = theDoc->GetActiveSlide(); + + // Slide, scene or component + if (theSelectedInstance + == theBridge->GetOwningComponentInstance(theCurrentActiveSlide)) { + CUICDMInstanceHandle theCurrentActiveSlideInstance = + theDoc->GetStudioSystem()->GetSlideSystem()->GetSlideInstance( + theCurrentActiveSlide); + + if (theBridge->IsSceneInstance(theSelectedInstance)) + theInspectableBase = new CUICDMSceneInspectable( + *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance); + else if (theBridge->IsComponentInstance(theSelectedInstance)) + theInspectableBase = new CUICDMInspectable( + *this, m_Core, theSelectedInstance, theCurrentActiveSlideInstance); + } + if (theInspectableBase == nullptr) { + if (theBridge->IsMaterialBaseInstance(theSelectedInstance)) + theInspectableBase = + new CUICDMMaterialInspectable(*this, m_Core, theSelectedInstance); + else + theInspectableBase = + new CUICDMInspectable(*this, m_Core, theSelectedInstance); + } + } + } break; + case Q3DStudio::SelectedValueTypes::Guide: { + UICDM::CUICDMGuideHandle theGuide = inSelectable.getData<UICDM::CUICDMGuideHandle>(); + theInspectableBase = CGuideInspectable::CreateInspectable(*m_Core, theGuide); + } break; + }; + } + + return theInspectableBase; +} + +void CStudioApp::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler) +{ + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceTime), 0, Qt::Key_Period); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceTime), 0, Qt::Key_Comma); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::AdvanceUltraBigTime), + Qt::ShiftModifier, Qt::Key_Greater); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::ReduceUltraBigTime), + Qt::ShiftModifier, Qt::Key_Less); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnToggleAutosetKeyframes), 0, Qt::Key_K); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveAs), + Qt::ControlModifier | Qt::ShiftModifier, Qt::Key_S); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSave), Qt::ControlModifier, + Qt::Key_S); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnSaveCopy), + Qt::ControlModifier | Qt::AltModifier, Qt::Key_S); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileNew), + Qt::ControlModifier, Qt::Key_N); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::OnFileOpen), + Qt::ControlModifier, Qt::Key_O); + inShortcutHandler->RegisterKeyUpEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackStop), 0, + Qt::Key_Space); + inShortcutHandler->RegisterKeyDownEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackPlay), 0, + Qt::Key_Space); + inShortcutHandler->RegisterKeyDownEvent( + new CDynHotKeyConsumer<CStudioApp>(this, &CStudioApp::PlaybackToggle), 0, + Qt::Key_Return); + + if (m_Views) + m_Views->RegisterGlobalKeyboardShortcuts(inShortcutHandler); +} + +//============================================================================= +/** + * Handles the Save command + * This will save the file, if the file has not been saved before this will + * do a save as operation. + * @return true if the file was successfully saved. + */ +bool CStudioApp::OnSave() +{ + CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath(); + if (!theCurrentDoc.IsFile()) { + return OnSaveAs(); + } else if (!theCurrentDoc.CanWrite()) { + m_Dialogs->DisplaySavingPresentationFailed(); + return false; + } else { + m_Core->OnSaveDocument(theCurrentDoc); + return true; + } +} + +//============================================================================= +/** + * Command handler for the File Save As menu option. + * This will prompt the user for a location to save the file out to then + * will perform the save. + * @return true if the file was successfully saved. + */ +bool CStudioApp::OnSaveAs() +{ + CUICFile theFile = m_Dialogs->GetSaveAsChoice().first; + if (theFile.GetPath() != "") { + m_Core->OnSaveDocument(theFile); + return true; + } + return false; +} + +//============================================================================= +/** + * Command handler for the File Save As menu option. + * This will prompt the user for a location to save the file out to then + * save a copy, leaving the original file open in the editor. + * @return true if the file was successfully saved. + */ +bool CStudioApp::OnSaveCopy() +{ + CUICFile theFile = m_Dialogs->GetSaveAsChoice().first; + if (theFile.GetPath() != "") { + // Send in a "true" to teh save function to indicate this is a copy + m_Core->OnSaveDocument(theFile, true); + return true; + } + return false; +} + +//============================================================================= +/** + * Call to load a new document. + * There should not be a currently active document when this is called. + * @param inDocument the path to the UIP file to be loaded. + * @param inShowStartupDialogOnError true to show startup dialog if loading document is error + * @return true if loading was successful + */ +bool CStudioApp::OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError) +{ + m_Core->GetDispatch()->FireOnProgressBegin(CString::fromQString(QObject::tr("Loading...")), inDocument.GetName(), + CString::fromQString(QObject::tr("Loading..."))); + + bool theLoadResult = false; + int theLoadErrorParameter = -1; + Q3DStudio::CString theErrorText; + try { + OnLoadDocumentCatcher(inDocument); + m_Core->GetDispatch()->FireOnOpenDocument(inDocument, true); + // Loading was successful + theLoadResult = true; + } catch (CUnsupportedFileFormatException &) { + theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It is either invalid or was made with an " + "old version of Studio.")); + // We've encountered a file format that is older than the current, OR + // corrupt files, unsupported file formats and illegal types. + } catch (CInvalidFileFormatException &) { + theErrorText = CString::fromQString(QObject::tr("The file could not be opened. It appears to have been made with a newer " + "version of Studio.")); + // Cannot support opening newer file format, the UIP or (AP ie client portion)'s version is + // mismatched. + } catch (CLoadReferencedFileException &inError) { + // referenced files (e.g. Data Files) failed to load + theErrorText.Format(L"%ls failed to load due to invalid referenced file: %ls.", + static_cast<const wchar_t *>(inDocument.GetName()), + inError.GetFilePath()); // TODO: Localize + const wchar_t *theDesc = inError.GetDescription(); + if (theDesc && wcslen(theDesc) > 0) { + // append any description is provided + theErrorText += L"\n"; + theErrorText += inError.GetDescription(); + } + } catch (CIOException &) { // provide specific error message if possible + if (inDocument.Exists() == false) + theLoadErrorParameter = IDS_ERROR_LOADFILENOTEXIST; + qCCritical(qt3ds::INTERNAL_ERROR) + << "Failed to load document, IO error (file may be unreadable or nonexistent)"; + } catch (...) { + qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document, uknown error"; + // We don't know exactly what went wrong during a load, but let studio 'fail gracefully'. + } + + if (theErrorText.Length()) { + qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to load document: " + << theErrorText.GetCharStar(); + } + + m_Core->GetDispatch()->FireOnProgressEnd(); + + // load fail + if (!theLoadResult) { + if (!theErrorText.IsEmpty()) + m_Dialogs->DisplayKnownErrorDialog(theErrorText); + else + m_Dialogs->DisplayLoadingPresentationFailed(inDocument, theLoadErrorParameter); + + m_Core->GetDispatch()->FireOnOpenDocument(inDocument, false); + + // Show startup dialog +#ifdef KDAB_TEMPORARILY_REMOVED + if (inShowStartupDialogOnError) + if (!ShowStartupDialog()) + PostQuitMessage(WM_QUIT); +#endif + } else { + m_Dialogs->ResetSettings(inDocument.GetPath()); + + m_subpresentations.clear(); + m_Core->GetDoc()->LoadUIASubpresentations(m_Core->GetDoc()->GetDocumentUIAFile(), + m_subpresentations); + } + + m_AuthorZoom = false; + + m_Core->GetDispatch()->FireAuthorZoomChanged(); + + return theLoadResult; +} + + +//============================================================================= +/** + * + */ +void CStudioApp::SaveUIAFile() +{ + QStringList list; + for (SubPresentationRecord r : m_subpresentations) { + list.append(r.m_type); + list.append(r.m_id); + list.append(r.m_argsOrSrc); + } + Q3DStudio::CFilePath doc(GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath()); + uic::state::IApplication::EnsureApplicationFile(doc.GetCharStar(), list); +} + +//============================================================================= +/** + * Called by OnLoadDocument, to allow the error reporting to be inserted. + * Because of the nature of the error reporting, OnLoadDocument has to have + * a certain structure that limits it (C type variables, no object destructors). + */ +void CStudioApp::OnLoadDocumentCatcher(const CUICFile &inDocument) +{ + { + CDispatchDataModelNotificationScope __scope(*m_Core->GetDispatch()); + m_Core->GetDoc()->CloseDocument(); + m_Core->GetDoc()->LoadDocument(inDocument); + } + + // Make sure the client scene is resized properly + if (m_Views) + m_Views->RecheckMainframeSizingMode(); +} + +void CStudioApp::OnFileOpen() +{ + if (PerformSavePrompt()) { + CUICFile theFile = m_Dialogs->GetFileOpenChoice(); + if (theFile.GetPath() != "") + OnLoadDocument(theFile); + } +} +using namespace std; + +void CStudioApp::OnFileNew() +{ + if (PerformSavePrompt()) { + pair<CUICFile, bool> theFile = m_Dialogs->GetNewDocumentChoice(); + if (theFile.first.GetPath() != "") + m_Core->OnNewDocument(theFile.first, theFile.second); + } +} + +bool CStudioApp::IsAuthorZoom() +{ + return m_AuthorZoom; +} + +void CStudioApp::SetAuthorZoom(bool inZoom) +{ + if (m_AuthorZoom != inZoom) { + m_AuthorZoom = inZoom; + m_Core->GetDispatch()->FireAuthorZoomChanged(); + } +} + +/////////////////////////////////////////////////////////////////////////////// +// These commands come over the dispatch from inside the core. The core doesn't +// have access to the CMsgRouter at the moment, so this relays the message. +void CStudioApp::OnAsynchronousCommand(CCmd *inCmd) +{ + CMsgRouter::GetInstance()->SendCommand(inCmd, m_Core); +} + +void CStudioApp::OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg) +{ + // Do nothing, it was used to show this in the status bar +} + +void CStudioApp::OnProgressBegin(const Q3DStudio::CString &inActionText, + const Q3DStudio::CString &inFileName, + const Q3DStudio::CString &inWindowTitle) +{ + m_Dialogs->DisplayProgressScreen(inActionText, inFileName, inWindowTitle); +} + +void CStudioApp::OnProgressEnd() +{ + m_Dialogs->DestroyProgressScreen(); +} + +void CStudioApp::OnAssetDeleteFail() +{ + m_Dialogs->DisplayAssetDeleteFailed(); +} + +void CStudioApp::OnPasteFail() +{ + m_Dialogs->DisplayPasteFailed(); +} + +void CStudioApp::OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage) +{ + m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_BUILDCONFIGS_ERROR_TITLE), inMessage, + CUICMessageBox::ICON_ERROR, false); +} + +void CStudioApp::OnSaveFail(bool inKnownError) +{ + qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to save project: " + << (inKnownError ? "KnownError" : "UnknownError"); + if (inKnownError) { + m_Dialogs->DisplaySavingPresentationFailed(); + } else { + m_Dialogs->DisplayKnownErrorDialog(::LoadResourceString(IDS_SAVE_UNKNOWN_ERROR)); + } +} + +void CStudioApp::OnProjectVariableFail(const Q3DStudio::CString &inMessage) +{ + m_Dialogs->DisplayEnvironmentVariablesError(inMessage); +} + +void CStudioApp::OnErrorFail(const Q3DStudio::CString &inText) +{ + qCCritical(qt3ds::INTERNAL_ERROR) << inText.GetCharStar(); + m_Dialogs->DisplayMessageBox(::LoadResourceString(IDS_PROJNAME), inText, + CUICMessageBox::ICON_ERROR, false); +} + +void CStudioApp::OnRefreshResourceFail(const Q3DStudio::CString &inResourceName, + const Q3DStudio::CString &inDescription) +{ + qCCritical(qt3ds::INTERNAL_ERROR) << "Failed to refresh resource: " + << inResourceName.GetCharStar(); + qCCritical(qt3ds::INTERNAL_ERROR) << inDescription.GetCharStar(); + m_Dialogs->DisplayRefreshResourceFailed(inResourceName, inDescription); +} + +void CStudioApp::OnNewPresentation() +{ + m_Core->GetDoc()->GetStudioSystem()->GetAnimationSystem()->SetAutoKeyframe( + CStudioPreferences::IsAutosetKeyframesOn()); + qCInfo(qt3ds::TRACE_INFO) << "New Presentation: " + << m_Core->GetDoc()->GetDocumentPath().GetAbsolutePath().GetCharStar(); +} + +void CStudioApp::OnPresentationModifiedExternally() +{ + int theUserChoice = m_Dialogs->DisplayChoiceBox( + ::LoadResourceString(IDS_TITLE_WARNING), + ::LoadResourceString(IDS_PRESENTATION_MODIFIED_EXTERNALLY), CUICMessageBox::ICON_WARNING); + if (theUserChoice == IDYES) { + CUICFile theCurrentDoc = m_Core->GetDoc()->GetDocumentPath(); + OnLoadDocument(theCurrentDoc); + } +} diff --git a/src/Authoring/Studio/_Win/Application/StudioApp.h b/src/Authoring/Studio/_Win/Application/StudioApp.h new file mode 100644 index 00000000..caea5158 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/StudioApp.h @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 1999-2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_STUDIO_APP_H +#define INCLUDED_STUDIO_APP_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "CmdLineParser.h" +#include "StudioObjectTypes.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include <minmax.h> +#include <gdiplus.h> +#endif +#include "DispatchListeners.h" +#include "UICDMHandles.h" + +#include <QApplication> + +namespace Q3DStudio { +class IInternalDirectoryWatchingSystem; +class IDirectoryWatchingSystem; +class ITickTock; +class IStudioRenderer; +struct SSelectedValue; +}; + +namespace UICDM { +class ISignalConnection; +}; + +struct StudioManipulationModes +{ + enum Enum { + Local, + Global, + }; +}; + +//============================================================================== +// Forwards +//============================================================================== +class CCore; +class CDialogs; +class CSplashView; +class CInspectableBase; +class CDirectoryWatchingSystemWrapper; +class CHotKeys; +class CViews; +class CMainFrame; +enum EStudioObjectType; +struct SubPresentationRecord; + +class CStudioApp : public CCoreAsynchronousEventListener, + public CAppStatusListener, + public CFailListener, + public CPresentationChangeListener // to setup auto set keyframes +{ +public: + CStudioApp(); + virtual ~CStudioApp(); + + // Overrides +public: + virtual BOOL InitInstance(int argc, char *argv[]); + virtual int ExitInstance(); + virtual int Run(); +#ifdef KDAB_TEMPORARILY_REMOVED + virtual UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault); + virtual BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue); + virtual ::CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, + LPCTSTR lpszDefault = nullptr); + virtual BOOL WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue); +#endif + + void OnAppAbout(); + +public: + void PerformShutdown(); +#ifdef KDAB_TEMPORARILY_REMOVED + static void StudioUnhandledCrashHandler(EXCEPTION_POINTERS *pExPtrs); +#endif + Q3DStudio::IDirectoryWatchingSystem &GetDirectoryWatchingSystem(); + void SetupTimer(long inMessageId, QWidget *inWnd); + Q3DStudio::ITickTock &GetTickTock(); + Q3DStudio::IStudioRenderer &GetRenderer(); + void ClearGuides(); + +protected: + int RunApplication(); + int BlankRunApplication(); + int RunCmdLineTests(const Q3DStudio::CString &inTestArgs); + int RunSystemTests(const Q3DStudio::CString &inTestArgs); + int OpenAndRunApplication(const Q3DStudio::CString &inFilename); + void InitCore(); + void InitHelpSystem(); + bool ShowStartupDialog(); + bool HandleWelcomeRes(int res, bool recursive); + + CCore *m_Core; + CSplashView *m_SplashPalette; ///< Startup splash palette + QString m_OldHelpFilePath; ///< Stores a pointer to the old + CCmdLineParser m_CmdLineParser; ///< Stores and returns execution modes + int m_UnitTestResults; ///< 0 on success; 1 on failure + bool m_IsSilent; ///< true indicates Studio running in silent mode (no GUI) + CViews *m_Views; + long m_ToolMode; + StudioManipulationModes::Enum + m_ManipulationMode; ///< Controls what space the tras,rot,and scale manipulations work in. + long m_SelectMode; + CDialogs *m_Dialogs; + long m_PlaybackTime; ///< Stores the playhead's starting position so that it can be restored + ///after playing the presentation for a little while + UICDM::CUICDMSlideHandle + m_PlaybackOriginalSlide; ///< Stores the current slide handle before playback started. + + std::shared_ptr<Q3DStudio::ITickTock> m_TickTock; + std::shared_ptr<Q3DStudio::IDirectoryWatchingSystem> m_DirectoryWatchingSystem; + std::shared_ptr<UICDM::ISignalConnection> m_DirectoryWatcherTicker; + std::shared_ptr<Q3DStudio::IStudioRenderer> m_Renderer; + bool m_AuthorZoom; + +private: +#ifdef KDAB_TEMPORARILY_REMOVED + Gdiplus::GdiplusStartupInput m_gdiplusStartupInput; + ULONG_PTR m_pGdiToken; +#endif + + bool m_welcomeShownThisSession; + // are we are launching welcome screen again due to + // user canceling file dialog? + bool m_goStraightToWelcomeFileDialog; + int m_tutorialPage; +public: + CMainFrame* m_pMainWnd; + + CCore *GetCore(); + CViews *GetViews(); + CDialogs *GetDialogs(); + long GetToolMode(); + void SetToolMode(long inToolMode); + long GetSelectMode(); + void SetSelectMode(long inSelectMode); + + StudioManipulationModes::Enum GetMinpulationMode() const; + void SetMinpulationMode(StudioManipulationModes::Enum inManipulationMode); + + bool CanUndo(); + bool CanRedo(); + void OnCopy(); + bool CanCopy(); + Q3DStudio::CString GetCopyType(); + void OnCut(); + bool CanCut(); + void OnPaste(); + bool CanPaste(); + Q3DStudio::CString GetPasteType(); + void SetSelectedObjectTimebarColor(); + bool CanChangeTimebarColor(); + void HandleSetChangedKeys(); + void DeleteSelectedKeys(); + void HandleDuplicateCommand(); + bool CanDuplicateObject(); + void OnToggleAutosetKeyframes(); + void SetAutosetKeyframes(bool inFlag); + void PlaybackPlay(); + void PlaybackStopNoRestore(); + void PlaybackRewind(); + void OnRevert(); + bool CanRevert(); + void OnFileOpenRecent(const CUICFile &inDocument); + bool PerformSavePrompt(); + void PlaybackStop(); + void AdvanceTime(); + void ReduceTime(); + void AdvanceUltraBigTime(); + void ReduceUltraBigTime(); + void PlaybackToggle(); + CInspectableBase *GetInspectableFromSelectable(Q3DStudio::SSelectedValue inSelectable); + void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler); + bool OnSave(); + bool OnSaveAs(); + bool OnSaveCopy(); + bool OnLoadDocument(const CUICFile &inDocument, bool inShowStartupDialogOnError = true); + void OnLoadDocumentCatcher(const CUICFile &inLocation); + void OnFileOpen(); + void OnFileNew(); + bool IsAuthorZoom(); + void SetAuthorZoom(bool inZoom); + + // CCoreAsynchronousEventListener + void OnAsynchronousCommand(CCmd *inCmd) override; + + // CAppStatusListener + void OnDisplayAppStatus(Q3DStudio::CString &inStatusMsg) override; + void OnProgressBegin(const Q3DStudio::CString &inActionText, + const Q3DStudio::CString &inFileName, + const Q3DStudio::CString &inWindowTitle) override; + void OnProgressEnd() override; + + // CFailListener + void OnAssetDeleteFail() override; + void OnPasteFail() override; + void OnBuildconfigurationFileParseFail(const Q3DStudio::CString &inMessage) override; + void OnSaveFail(bool inKnownError) override; + void OnProjectVariableFail(const Q3DStudio::CString &inMessage) override; + void OnErrorFail(const Q3DStudio::CString &inText) override; + void OnRefreshResourceFail(const Q3DStudio::CString &inResourceName, + const Q3DStudio::CString &inDescription) override; + + // CPresentationChangeListener + void OnNewPresentation() override; + void OnPresentationModifiedExternally() override; + + Q3DStudio::CString m_pszHelpFilePath; + + QVector<SubPresentationRecord> m_subpresentations; + void SaveUIAFile(); +}; + +extern CStudioApp g_StudioApp; + +#endif // INCLUDED_STUDIO_APP_H diff --git a/src/Authoring/Studio/_Win/Application/StudioColors.h b/src/Authoring/Studio/_Win/Application/StudioColors.h new file mode 100644 index 00000000..776047a5 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/StudioColors.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2002 Anark Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_STUDIOCOLORS_H +#define INCLUDED_STUDIOCOLORS_H + +#pragma once + +//============================================================================== +// Studio colors +//============================================================================== + +const COLORREF STUDIO_MATTE_COLOR = RGB(119, 122, 125); // GetSysColor( COLOR_APPWORKSPACE ); +const COLORREF MENU_IMAGELIST_BACKCOLOR = RGB(255, 0, 255); // RGB( 255, 128, 0 ); + +//============================================================================== +// TimeBar colors +//============================================================================== + +// TimeBar pen colors + +const COLORREF TIMEBAR_PEN_COLOR_INNER = RGB(254, 254, 254); +const COLORREF TIMEBAR_PEN_COLOR_INACTIVE = RGB(132, 130, 132); +const COLORREF TIMEBAR_PEN_COLOR_ACTIVE = RGB(0, 0, 0); + +// TimeBar shadow colors + +const COLORREF TIMEBAR_INACTIVE_SHADOW_COLOR = RGB(0xC4, 0xC4, 0xC4); +const COLORREF TIMEBAR_ACTIVE_SHADOW_COLOR = RGB(0x84, 0x84, 0x84); + +// TimeBar comment colors + +const COLORREF TIMEBAR_COMMENT_ACTIVE_TC = RGB(0x00, 0x00, 0x00); +const COLORREF TIMEBAR_COMMENT_INACTIVE_TC = RGB(0x72, 0x72, 0x72); + +const COLORREF COLOR_TIMEBAR_DISABLED = RGB(207, 207, 207); +const COLORREF COLOR_TIMEBAR_BEHAVIOR = + RGB(148, 189, 150); // RGB( 92, 164, 131 );//RGB( 243, 243, 243 ); +const COLORREF COLOR_TIMEBAR_MATERIAL = + RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 239, 230, 210 ); +const COLORREF COLOR_TIMEBAR_IMAGE = + RGB(194, 155, 181); // RGB( 190, 184, 152 ); //RGB( 198, 225, 199 ); +const COLORREF COLOR_TIMEBAR_LOCKED = RGB(228, 228, 228); + +const COLORREF TIMEBAR_COLOR_TRANSPARENT = RGB(255, 0, 255); + +// A constant to represent color for inner white rectangle of center bar +const COLORREF COLOR_INNER_BAR_RECTANGLE = RGB(253, 253, 254); +// Default timebar fill color +const COLORREF COLOR_TIMEBAR_DEFAULT_FILL = RGB( + 163, 178, 227); // RGB( 174, 183, 210 ); //RGB( 148, 166, 189 ); //RGB( 211, 226, 240 ); + +// Selected time bar colors + +const COLORREF COLOR_TIMEBAR_SELECTED = RGB(75, 75, 75); // RGB( 14, 49, 98 ); +const COLORREF COLOR_TIMEBAR_SELECTED_TEXT = RGB(255, 255, 255); +const COLORREF COLOR_TIMEBAR_SELECTED_BEHAVIOR = RGB(174, 216, 176); +const COLORREF COLOR_TIMEBAR_SELECTED_HIGHLIGHT = RGB(27, 73, 136); + +// const COLORREF COLOR_SELECTED_TIMEBAR_3DOBJECT = RGB( 190, 191, 202 +// ); + +const COLORREF COLOR_TIMEBAR_HIGHLIGHT = RGB(190, 191, 202); +const COLORREF COLOR_TIMEBAR_HIGHLIGHT_GROUP = RGB(174, 216, 176); + +const COLORREF COLOR_PLAYHEADSCRUBTIME = RGB(0, 85, 0); + +//============================================================================== +// Timeline colors +//============================================================================== + +const BOOL INVERT_TIMELINE_TEXT_COLOR = TRUE; + +const COLORREF COLOR_SELECTEDTEXT = RGB(255, 255, 255); +const COLORREF COLOR_SELECTEDTEXTBKGRND = RGB(14, 49, 98); +const COLORREF COLOR_DRAGDROPTARGETTEXT = RGB(255, 255, 255); +const COLORREF COLOR_DRAGDROPTARGETBKGRND = RGB(24, 98, 198); + +const COLORREF COLOR_SHADOW = RGB(165, 162, 161); // RGB( 132, 130, 132 ); + +const COLORREF COLOR_PLAYHEADLINE = RGB(0xDD, 0x04, 0x05); +const COLORREF COLOR_BACKGRND = + GetSysColor(COLOR_3DFACE); // RGB( 206, 203, 198 ); //RGB( 0xE7, 0xE7, 0xE7 ); +const COLORREF COLOR_SELECTED = RGB(255, 255, 255); +const COLORREF COLOR_DEFAULTOBJECTS = RGB(206, 203, 198); // RGB( 0xE7, 0xE7, 0xE7 ); +const COLORREF COLOR_3DOBJECTS = RGB(206, 203, 198); // RGB( 0xC7, 0xD4, 0xE1 ); +const COLORREF COLOR_DEFAULTOBJECTHIGHLIGHT = RGB(222, 223, 222); // RGB( 255, 255, 255 ); +const COLORREF COLOR_DRAGHIGHLIGHT = RGB(255, 255, 255); +const COLORREF COLOR_INSERTMARK = RGB(0x00, 0x00, 0x00); +const COLORREF COLOR_TIMELINEINSERTMARK = RGB(0x00, 0x00, 0xFF); +const COLORREF COLOR_TEXTCOLOR = RGB(0x00, 0x00, 0x00); +const COLORREF COLOR_CONTAINERTEXTCOLOR = RGB(80, 80, 140); +const COLORREF COLOR_LOCKEDTEXTCOLOR = RGB(0x80, 0x80, 0x80); +const COLORREF COLOR_INDEPENDENTOBJECT = RGB(0x80, 0x80, 0x80); +const COLORREF COLOR_SPLITLINE = RGB(0x00, 0x00, 0x7F); +const COLORREF COLOR_SEPARATORLINE = RGB(0x00, 0x00, 0x20); +const COLORREF COLOR_LIGHTMODEL = RGB(206, 203, 198); // RGB( 198, 211, 224 ); +const COLORREF COLOR_GROUP = + RGB(206, 203, 198); // RGB( 198, 211, 224 ); //RGB( 199, 220, 193 ); +const COLORREF COLOR_PROPERTY = RGB(228, 225, 219); // RGB( 241, 241, 241 ); +const COLORREF COLOR_CHANNEL = RGB(228, 225, 219); // RGB( 241, 241, 241 ); +const COLORREF COLOR_CONTAINER = + RGB(228, 225, 219); // RGB( 206, 203, 198 ); //RGB( 231, 231, 231 ); +const COLORREF COLOR_MATERIAL = RGB(210, 210, 210); // RGB( 170, 224, 170 ); +const COLORREF COLOR_CONTAINERHIGHLIGHT = RGB(193, 180, 180); +const COLORREF COLOR_BEHAVIOR = RGB(199, 220, 193); +const COLORREF COLOR_BEHAVIORHIGHLIGHT = RGB(255, 255, 255); +const COLORREF COLOR_IMGLISTTRANSPARENT = RGB(0xFF, 0x00, 0xFF); +const COLORREF COLOR_TIMEMEASURE = GetSysColor(COLOR_3DFACE); // RGB( 170, 166, 160 ); + +#endif diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp new file mode 100644 index 00000000..e3e25fa1 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.cpp @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "StudioDefs.h" +#include "Strings.h" +#include "StringLoader.h" + +//============================================================================== +// Includes +//============================================================================== +#include "SubPresentationsDlg.h" +#include "ui_SubPresentationsDlg.h" +#include "ProductInfo.h" +#include "HotKeys.h" +#include "Preferences.h" +#include "StudioPreferences.h" + +#include <QtGui/qevent.h> +#include <QtGui/qpainter.h> +#include <QtCore/qtimer.h> +#include <QtWidgets/qfiledialog.h> + +CSubPresentationsDlg::CSubPresentationsDlg( + const QString &directory, + const QVector<SubPresentationRecord> &subpresentations, + QWidget *parent) + : QDialog(parent, Qt::MSWindowsFixedSizeDialogHint) + , m_directory(directory) + , m_records(subpresentations) + , m_ui(new Ui::SubPresentationsDlg) +{ + m_ui->setupUi(this); + + connect(m_ui->deleteButton, &QPushButton::clicked, this, + &CSubPresentationsDlg::OnDeletePresentation); + connect(m_ui->pushButtonNew, &QPushButton::clicked, this, + &CSubPresentationsDlg::OnNewPresentation); + connect(m_ui->pushButtonBrowse, &QPushButton::clicked, this, + &CSubPresentationsDlg::OnBrowsePresentation); + connect(m_ui->comboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), + this, &CSubPresentationsDlg::OnSelectPresentation); + connect(m_ui->lineEditId, &QLineEdit::textEdited, this, &CSubPresentationsDlg::OnIdChanged); + + OnInitDialog(); +} + +CSubPresentationsDlg::~CSubPresentationsDlg() +{ + delete m_ui; +} + +QVector<SubPresentationRecord> CSubPresentationsDlg::subpresentations() const +{ + return m_records; +} + +void CSubPresentationsDlg::OnInitDialog() +{ + current = -1; + if (m_records.size() > 0) { + for (SubPresentationRecord rec : m_records) + m_ui->comboBox->addItem(rec.m_id); + current = 0; + m_ui->lineEditId->setText(m_records[0].m_id); + m_ui->lineEditPreview->setText(m_records[0].m_argsOrSrc); + } + m_ui->lineEditPreview->setReadOnly(true); + m_ui->buttonBox->setFocusPolicy(Qt::NoFocus); +} + +void CSubPresentationsDlg::OnSelectPresentation(int selectionIndex) +{ + if (selectionIndex >= 0 && selectionIndex < m_records.size()) { + current = selectionIndex; + m_ui->lineEditId->setText(m_records[current].m_id); + m_ui->lineEditPreview->setText(m_records[current].m_argsOrSrc); + } else { + m_ui->lineEditId->setText(QString()); + m_ui->lineEditPreview->setText(QString()); + } +} + +void CSubPresentationsDlg::OnDeletePresentation() +{ + if (current >= 0 && current < m_records.size()) { + m_records.remove(current); + m_ui->comboBox->removeItem(current); + current = qMax(current - 1, 0); + if (m_records.size() == 0) + current = -1; + OnSelectPresentation(current); + } +} + +void CSubPresentationsDlg::OnNewPresentation() +{ + int index = m_records.size(); + m_records.push_back( + SubPresentationRecord(QStringLiteral("presentation-qml"), + QStringLiteral("presentation-id"), QString())); + m_ui->comboBox->addItem(QStringLiteral("presentation-id")); + m_ui->comboBox->setCurrentIndex(index); + OnSelectPresentation(index); +} + +void CSubPresentationsDlg::OnBrowsePresentation() +{ + const QString file = QDir::toNativeSeparators( + QFileDialog::getOpenFileName(nullptr, nullptr, m_directory, + QStringLiteral("*.qml; *.uip"))); + QString shortFile = file; + int subdir = file.indexOf(m_directory); + if (subdir >= 0) + shortFile.remove(subdir, m_directory.size() + 1); + + QFileInfo fileInfo(file); + if (fileInfo.exists()) { + if (fileInfo.suffix() == QStringLiteral("qml")) + m_records[current].m_type = QStringLiteral("presentation-qml"); + else + if (fileInfo.suffix() == QStringLiteral("uip")) + m_records[current].m_type = QStringLiteral("presentation"); + + m_records[current].m_argsOrSrc = shortFile; + m_ui->lineEditPreview->setText(shortFile); + } +} + +void CSubPresentationsDlg::OnIdChanged(const QString &text) +{ + m_records[current].m_id = text; + m_ui->comboBox->setItemText(current, text); +} + +void CSubPresentationsDlg::on_buttonBox_accepted() +{ + QDialog::accept(); +} + +void CSubPresentationsDlg::on_buttonBox_rejected() +{ + QDialog::reject(); +} diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h new file mode 100644 index 00000000..75828c4e --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SUBPRESENTATIONSDLG_H +#define SUBPRESENTATIONSDLG_H + +#include <QtWidgets/qdialog.h> + +#include "UICString.h" +#include "Doc.h" + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { + class SubPresentationsDlg; +} +QT_END_NAMESPACE + +class CSubPresentationsDlg : public QDialog +{ + Q_OBJECT +public: + CSubPresentationsDlg(const QString &directory, + const QVector<SubPresentationRecord> &subpresentations, + QWidget* parent = nullptr); + ~CSubPresentationsDlg(); + + // Implementation +protected: + + void OnInitDialog(); + +public: + + QVector<SubPresentationRecord> subpresentations() const; + + void OnDeletePresentation(); + void OnNewPresentation(); + void OnBrowsePresentation(); + void OnSelectPresentation(int selectionIndex); + void OnIdChanged(const QString &text); + +private Q_SLOTS: + void on_buttonBox_accepted(); + void on_buttonBox_rejected(); + +private: + QString m_directory; + QVector<SubPresentationRecord> m_records; + Ui::SubPresentationsDlg *m_ui; + int current; +}; + +#endif diff --git a/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui new file mode 100644 index 00000000..db673925 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/SubPresentationsDlg.ui @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SubPresentationsDlg</class> + <widget class="QDialog" name="SubPresentationsDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>512</width> + <height>169</height> + </rect> + </property> + <property name="windowTitle"> + <string>Sub-presentations</string> + </property> + <widget class="QWidget" name="horizontalLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>130</y> + <width>491</width> + <height>31</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="horizontalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>491</width> + <height>111</height> + </rect> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Sub-presentation</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Presentation Id</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Filename</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QComboBox" name="comboBox"/> + </item> + <item> + <widget class="QLineEdit" name="lineEditId"> + <property name="toolTip"> + <string><html><head/><body><p>Edit the name of the sub-presentation</p></body></html></string> + </property> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="lineEditPreview"> + <property name="text"> + <string/> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QPushButton" name="deleteButton"> + <property name="toolTip"> + <string><html><head/><body><p>Delete currently selected sub-presentation</p></body></html></string> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButtonNew"> + <property name="toolTip"> + <string><html><head/><body><p>Add new sub-presentation</p></body></html></string> + </property> + <property name="text"> + <string>Add</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="pushButtonBrowse"> + <property name="toolTip"> + <string><html><head/><body><p>Browse for the sub-presentation source</p></body></html></string> + </property> + <property name="text"> + <string>Browse...</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/Authoring/Studio/_Win/Application/TextLink.cpp b/src/Authoring/Studio/_Win/Application/TextLink.cpp new file mode 100644 index 00000000..a68aaea8 --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/TextLink.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +#ifdef _DEBUG +//#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//============================================================================== +// Includes +//============================================================================== + +#include "TextLink.h" +#include "Resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CTextLink class + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CTextLink::CTextLink() + : CBaseLink() +{ + // Set default colors + m_ColorText = CStudioPreferences::GetNormalColor(); + m_ColorBackground = CStudioPreferences::GetBaseColor(); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CTextLink::~CTextLink() +{ +} + +//============================================================================== +/** + * SetColor: Sets the text color and background color + * + * @param inText Text color for the control. + * @param inBackground Background color for the control. + */ +//============================================================================== +void CTextLink::SetColor(COLORREF inText, COLORREF inBackground) +{ + m_ColorText = inText; + m_ColorBackground = inBackground; +} + +//============================================================================== +/** + * ShowLink: Shows the link. + * + * @param None + */ +//============================================================================== +void CTextLink::ShowLink() +{ + if (IsWindow(m_hWnd)) { + ShowTextLink(m_ColorText, m_ColorBackground, DT_VCENTER | DT_SINGLELINE, m_bCapture); + } +} diff --git a/src/Authoring/Studio/_Win/Application/TextLink.h b/src/Authoring/Studio/_Win/Application/TextLink.h new file mode 100644 index 00000000..85f5fedf --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/TextLink.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _TEXTLINK_H_ +#define _TEXTLINK_H_ + +#include "BaseLink.h" + +///////////////////////////////////////////////////////////////////////////// +// CTextLink window + +class CTextLink : public CBaseLink +{ + // Construction +public: + CTextLink(); + + // Attributes +public: + // Operations +public: + virtual void SetColor(COLORREF inText, COLORREF inBackground); + +protected: + COLORREF m_ColorText; + COLORREF m_ColorBackground; + + virtual void ShowLink(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTextLink) + //}}AFX_VIRTUAL + + // Implementation +public: + virtual ~CTextLink(); + + // Generated message map functions +protected: + //{{AFX_MSG(CTextLink) + //}}AFX_MSG +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/Authoring/Studio/_Win/Application/WebLink.cpp b/src/Authoring/Studio/_Win/Application/WebLink.cpp new file mode 100644 index 00000000..258bdffb --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/WebLink.cpp @@ -0,0 +1,440 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +#ifdef _DEBUG +//#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +//============================================================================== +// Includes +//============================================================================== + +#include "WebLink.h" +#include "Resource.h" +#include "BCMenu.h" +#include "StudioColors.h" + +///////////////////////////////////////////////////////////////////////////// +// CWebLink class + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CWebLink::CWebLink() + : CBaseLink() +{ + // Set default link colors + m_ColorLink = CStudioPreferences::GetMasterColor(); // green + m_ColorHighlight = RGB(0xFF, 0x00, 0x00); // red + m_ColorVisited = RGB(0x7F, 0x00, 0x7F); // purple + m_ColorBackground = CStudioPreferences::GetDarkBaseColor(); + + m_bVisited = FALSE; + + m_URL.Empty(); + + m_Bitmap = nullptr; + + m_bPopup = FALSE; +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CWebLink::~CWebLink() +{ +} + +//============================================================================== +// Message Map +//============================================================================== + +BEGIN_MESSAGE_MAP(CWebLink, CWnd) +//{{AFX_MSG_MAP(CWebLink) +ON_WM_PAINT() +ON_WM_SETCURSOR() +ON_WM_LBUTTONDOWN() +ON_WM_MOUSEMOVE() +ON_WM_CONTEXTMENU() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +/** + * SetURL: Sets the URL for the control. + * + * @param inURL URL to point the default browser to when the control is clicked. + */ +//============================================================================== +void CWebLink::SetURL(CString inURL) +{ + m_URL = inURL; +} + +//============================================================================== +/** + * SetImage: Sets an bitmap image for the control. + * + * @param inResBmp BITMAP resource for the image to load. + * @param inAutoSizeFlag TRUE if the control should be resized to the image size. + */ +//============================================================================== +void CWebLink::SetImage(UINT inResBmp, bool inAutoSizeFlag) +{ + HBITMAP theBitmap = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inResBmp), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + if (theBitmap != nullptr) { + this->SetImage(theBitmap, inAutoSizeFlag); + } +} + +//============================================================================== +/** + * SetImage: Sets an bitmap image for the control. + * + * @param inBitmap HBITMAP handle of the loaded bitmap. + * @param inAutoSizeFlag TRUE if the control should be resized to the image size. + */ +//============================================================================== +void CWebLink::SetImage(HBITMAP inBitmap, bool inAutoSizeFlag) +{ + m_Bitmap = inBitmap; + + if (inAutoSizeFlag && m_Bitmap != nullptr) { + // Resize this control based on the size of the bitmap. + BITMAP theBitmapStruct; + int theWidth, theHeight; + + GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct); + theWidth = theBitmapStruct.bmWidth; + theHeight = theBitmapStruct.bmHeight; + + SetWindowPos(nullptr, 0, 0, theWidth, theHeight, SWP_NOZORDER | SWP_NOMOVE); + } + + this->ShowLink(); +} + +//============================================================================== +/** + * SetText: Sets the text for the control. + * + * @param inText Text for the control. + */ +//============================================================================== +void CWebLink::SetText(CString inText) +{ + SetWindowText(inText); + m_Bitmap = nullptr; + this->ShowLink(); +} + +COLORREF CWebLink::GetColor() +{ + if (m_bCapture) { + return m_ColorHighlight; + } else { + if (m_bVisited) + return m_ColorVisited; + else + return m_ColorLink; + } +} + +//============================================================================== +/** + * ShowLink: Shows the link. + * + * @param None + */ +//============================================================================== +void CWebLink::ShowLink() +{ + if (IsWindow(m_hWnd)) { + // Is the link represented by an image? + if (m_Bitmap != nullptr) { + ShowBitmapLink(); + } else { + ShowTextLink(GetColor(), m_ColorBackground, DT_WORDBREAK | SS_LEFT, true); + } + } +} + +//============================================================================== +/** + * ShowLink: Shows the bitmap link. + * + * @param None + */ +//============================================================================== +void CWebLink::ShowBitmapLink() +{ + if (IsWindow(m_hWnd)) { + CRect theRect; + CDC *theDC; + CDC theMemDC; + + BITMAP theBitmapStruct; + long theWidth, theHeight; + CBrush theBrush; + + theDC = GetDC(); + theMemDC.CreateCompatibleDC(theDC); + CBitmap *theBitmap = CBitmap::FromHandle(m_Bitmap); + + CBitmap *theOldBmp = (CBitmap *)theMemDC.SelectObject(theBitmap); + + GetObject(m_Bitmap, sizeof(BITMAP), &theBitmapStruct); + theWidth = theBitmapStruct.bmWidth; + theHeight = theBitmapStruct.bmHeight; + + theDC->BitBlt(0, 0, theWidth, theHeight, &theMemDC, 0, 0, SRCCOPY); + + COLORREF theColor = GetColor(); + if (theColor == m_ColorHighlight || theColor == m_ColorVisited) { + // Draw a highlight frame + GetClientRect(&theRect); + + theBrush.CreateSolidBrush(theColor); + theDC->FrameRect(&theRect, &theBrush); + theBrush.DeleteObject(); + } + + theMemDC.SelectObject(theOldBmp); + + theMemDC.DeleteDC(); + ReleaseDC(theDC); + } +} + +//============================================================================== +/** + * JumpLink: Jumps to the link URL. + * + * @param None + */ +//============================================================================== +void CWebLink::JumpLink() +{ + CString theWebLink; + + GetWindowText(theWebLink); + + if (!m_URL.IsEmpty()) + theWebLink = m_URL; + + if (!theWebLink.IsEmpty()) { + this->OpenURL(theWebLink); + } +} + +//============================================================================== +/** + * OpenURL: Opens the specified URL with the default browser. + * + * @param inURL URL to open with the browser. + */ +//============================================================================== +void CWebLink::OpenURL(CString inURL) +{ + HCURSOR thePrevCursor; + + thePrevCursor = SetCursor(LoadCursor(nullptr, IDC_APPSTARTING)); + ShellExecute(GetSafeHwnd(), L"open", inURL, nullptr, nullptr, SW_SHOWNORMAL); + SetCursor(thePrevCursor); +} + +///////////////////////////////////////////////////////////////////////////// +// CWebLink message handlers + +//============================================================================== +/** + * OnSetCursor + * + * Handle the WM_SETCURSOR message. + * + * @param inWnd Pointer to the parent CWnd object. + * @param inHitTest Specifies the hit-test area code. The hit test determines the + *cursor�s location. + * @param inMessage Specifies the mouse message number. + */ +//============================================================================== +BOOL CWebLink::OnSetCursor(CWnd *inWnd, UINT inHitTest, UINT inMessage) +{ + UNREFERENCED_PARAMETER(inWnd); + UNREFERENCED_PARAMETER(inHitTest); + UNREFERENCED_PARAMETER(inMessage); + + if (m_bPopup) { + SetCursor(LoadCursor(nullptr, IDC_ARROW)); + } else { + SetCursor(LoadCursor(nullptr, IDC_HAND)); + } + + return TRUE; +} + +//============================================================================== +/** + * OnLButtonDown + * + * Windows callback handler for the WM_LBUTTONDOWN message + * + * @param inFlags Flags for the left button down message + * @param inPoint Point where the mouse was left clicked (client coordinates) + */ +//============================================================================== +void CWebLink::OnLButtonDown(UINT inFlags, CPoint inPoint) +{ + UNREFERENCED_PARAMETER(inFlags); + UNREFERENCED_PARAMETER(inPoint); + + if (IsWindowEnabled()) { + m_bCapture = FALSE; + ReleaseCapture(); + + m_bVisited = TRUE; + this->ShowLink(); + + this->JumpLink(); + } +} + +//============================================================================== +/** + * OnContextMenu: Handle for the WM_CONTEXTMENU message. + * + * @param inWnd Window for the context menu. + * @param inPoint Mouse position when the right button was clicked. + */ +//============================================================================== +void CWebLink::OnContextMenu(CWnd *inWnd, CPoint inPoint) +{ + UNREFERENCED_PARAMETER(inWnd); + + BCMenu theContextMenu; + BCMenu *thePopupMenu = nullptr; + long theMenuCmd; + + ReleaseCapture(); + + // Load the context menu + theContextMenu.LoadMenu(IDR_WEBLINK_CONTEXT_MENU); +#ifdef _USECONTENTMENUIMAGES_ + theContextMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR); + theContextMenu.LoadToolbar(IDR_WEBLINKCONTEXTTOOLBAR); +#endif + + thePopupMenu = (BCMenu *)theContextMenu.GetSubMenu(0); + + // Set the default menu item to "Open" + SetMenuDefaultItem(thePopupMenu->m_hMenu, IDM_OPENLINK, FALSE); + + m_bPopup = TRUE; + + // Show the context menu + theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_NONOTIFY | TPM_RETURNCMD, + inPoint.x, inPoint.y, this); + + m_bPopup = FALSE; + + m_bCapture = FALSE; + + theContextMenu.DestroyMenu(); + + this->ShowLink(); + + // Handle the popup menu command + + switch (theMenuCmd) { + case IDM_OPENLINK: + this->JumpLink(); + break; + + case IDM_COPYSHORTCUT2: + this->CopyShortcut(); + break; + + default: + break; + } + + theContextMenu.DestroyMenu(); +} + +//============================================================================== +/** + * CopyShortcut: Copy the link URL text to the clipboard. + * + * @param None + */ +//============================================================================== +void CWebLink::CopyShortcut() +{ + // Open the clipboard so we can copy data to it. + if (OpenClipboard()) { + DWORD theBufferSize; + HGLOBAL theGlobalBuffer; + LPSTR theClipboardText; + + // Determine the buffer size, based on the length of the URL + theBufferSize = m_URL.GetLength(); + + // Clear the contents of the clipboard + ::EmptyClipboard(); + + // Allocate a global buffer and copy the text to it + theGlobalBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, theBufferSize + 1); + theClipboardText = (LPSTR)GlobalLock(theGlobalBuffer); + + CopyMemory(theClipboardText, m_URL, theBufferSize + 1); + + // Unlock the buffer + GlobalUnlock(theGlobalBuffer); + + // Pass the data to the clipboard + SetClipboardData(CF_TEXT, theGlobalBuffer); + + // Close the clipboard, but do not GlobalFree() the global buffer + CloseClipboard(); + } +} diff --git a/src/Authoring/Studio/_Win/Application/WebLink.h b/src/Authoring/Studio/_Win/Application/WebLink.h new file mode 100644 index 00000000..4ca3dede --- /dev/null +++ b/src/Authoring/Studio/_Win/Application/WebLink.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _WEBLINK_H_ +#define _WEBLINK_H_ + +#include "BaseLink.h" + +///////////////////////////////////////////////////////////////////////////// +// CWebLink window + +class CWebLink : public CBaseLink +{ + // Construction +public: + CWebLink(); + + // Attributes +public: + // Operations +public: + virtual void SetImage(UINT uiResBmp, bool bAutoSize = true); + virtual void SetImage(HBITMAP hBmp, bool bAutoSize = true); + virtual void SetText(CString inText); + virtual void SetURL(CString inURL); + +protected: + COLORREF m_ColorLink; + COLORREF m_ColorHighlight; + COLORREF m_ColorVisited; + COLORREF m_ColorBackground; + + bool m_bVisited; + bool m_bPopup; + + HBITMAP m_Bitmap; + + CString m_URL; + + virtual COLORREF GetColor(); + + virtual void CopyShortcut(); + + virtual void JumpLink(); + + virtual void OpenURL(CString inURL); + + virtual void ShowLink(); + + virtual void ShowBitmapLink(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWebLink) + //}}AFX_VIRTUAL + + // Implementation +public: + virtual ~CWebLink(); + + // Generated message map functions +protected: + //{{AFX_MSG(CWebLink) + virtual afx_msg BOOL OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message); + virtual afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + virtual afx_msg void OnContextMenu(CWnd *pWnd, CPoint pos); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.cpp b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp new file mode 100644 index 00000000..54039331 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/AppFonts.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "AppFonts.h" +#include "StudioPreferences.h" +#include "StringLoader.h" + +//============================================================================= +/** + * Constructor for a CAppFonts object. + */ +//============================================================================= +CAppFonts::CAppFonts() +{ + // Normal font + const QString theFontFace = CStudioPreferences::GetFontFaceName(); + Q3DStudio::CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE); + + m_NormalFont.setFamily(theFontFace); + m_NormalFont.setPointSize(13); // atoi( theFontSize.GetCharStar( ) ); +} + +//============================================================================== +/** + * Releases the object. + */ +//============================================================================== +CAppFonts::~CAppFonts() +{ +} + +//============================================================================== +/** + * Returns a pointer to the only instance of this class. Automatically cleaned + * up when the program exits. + */ +//============================================================================== +CAppFonts *CAppFonts::GetInstance() +{ + static CAppFonts theAppFonts; + return &theAppFonts; +} + +//============================================================================== +/** + * Returns the normal font for use on GUI elements for the application. + */ +//============================================================================== +QFont CAppFonts::GetNormalFont() +{ + return m_NormalFont; +} diff --git a/src/Authoring/Studio/_Win/Controls/AppFonts.h b/src/Authoring/Studio/_Win/Controls/AppFonts.h new file mode 100644 index 00000000..e2036c0e --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/AppFonts.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== + +#ifndef INCLUDED_APP_FONTS_H +#define INCLUDED_APP_FONTS_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +#include <QFont> +//============================================================================== +/** + * Dispatches commands + */ +//============================================================================== +class CAppFonts +{ +public: + CAppFonts(); + virtual ~CAppFonts(); + static CAppFonts *GetInstance(); + QFont GetNormalFont(); + +private: + QFont m_NormalFont; +}; + +#endif // INCLUDED_APP_FONTS_H diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp new file mode 100644 index 00000000..34076704 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stdafx.h" + +#include "BufferedRenderer.h" +#include "AppFonts.h" + + +//============================================================================= +/** + * Create a buffered renderer. + * @param inSize the size of this renderer. + */ +CBufferedRenderer::CBufferedRenderer(const QSize &inSize) + : CWinRenderer() +{ + m_CurrentBitmap = QPixmap(inSize); + + // KDAB_TODO: I don't see why m_OldBitmap is needed, nor what is the difference between CBufferedRenderer and COffscreenRenderer + m_OldBitmap = m_CurrentBitmap; + + m_painter = new QPainter(&m_CurrentBitmap); + QFont font = CAppFonts::GetInstance()->GetNormalFont(); + m_painter->setFont(font); + + m_Size = inSize; + + PushClippingRect(QRect(QPoint(0,0), inSize)); +} + + +//============================================================================= +/** + * Destructor + */ +CBufferedRenderer::~CBufferedRenderer() +{ + delete m_painter; + m_painter = nullptr; +} + +//============================================================================= +/** + * Copy this BufferedRenderer to inRenderer using alpha blend. + * This will semi-transparently copy the contents of this buffer to inRenderer + * using the alpha. + * @param inRenderer the destination renderer. + * @param inAlpha the opacity, 255 = opaque 0 = transparent. + */ +/*void CBufferedRenderer::TransparentBltTo( CRenderer* inRenderer, short inAlpha ) +{ + + CPt theDestination; + theDestination.Offset( inRenderer->GetTranslation( ) ); + + AlphaBlendExt( inRenderer->GetGraphicsDevice( )->m_hDC, (short)theDestination.x, +(short)theDestination.y, (short)m_Size.x, (short)m_Size.y, m_DC->m_hDC, 0, 0, (short)m_Size.x, +(short)m_Size.y, inAlpha ); +// ::DrawAlphaBlendBitmap( inRenderer->GetDC( ), (short)theDestination.x, +(short)theDestination.y, m_CurrentBitmap, (short)m_Size.x, (short)m_Size.y, 0, 0, inAlpha ); + +}*/ + +//============================================================================== +/** + * Draws a bitmap using alpha blending. Works in NT/2000/9x + * + * @param inDCDest Destination device context + * @param inX X coordinate for drawing + * @param inY Y coordinate for drawing + * @param inWidth Drawing width + * @param inHeight Drawing height + * @param inDCSrc Source device context + * @param inSourceX X source coordinate + * @param inSourceY Y source coordinate + * @param inSourceWidth Source drawing width + * @param inSourceHeight Source drawing height + * @param inAlpha Alpha blend: 0-255, where 255 is opaque + */ +//============================================================================== +/*bool CBufferedRenderer::AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short +inHeight, HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight, +short inAlpha ) +{ + BITMAPINFOHEADER theBMI; + + theBMI.biSize = sizeof( BITMAPINFOHEADER ); + theBMI.biWidth = inWidth; + theBMI.biHeight = inHeight; + theBMI.biPlanes = 1; + theBMI.biBitCount = 32; // 24 bits + alpha channel + theBMI.biCompression = BI_RGB; // no compression + theBMI.biSizeImage = 0; + theBMI.biXPelsPerMeter = 0; + theBMI.biYPelsPerMeter = 0; + theBMI.biClrUsed = 0; // use the whole palette + theBMI.biClrImportant = 0; + + BYTE* theSrcBits; + HBITMAP theBmpSrc; + + // Create DIB section in shared memory + theBmpSrc = CreateDIBSection( inDCSrc, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** ) +&theSrcBits, 0, 0L ); + + BYTE* theDestBits; + HBITMAP theBmpDest; + + // Create DIB section in shared memory + theBmpDest = CreateDIBSection( inDCDest, ( BITMAPINFO* ) &theBMI, DIB_RGB_COLORS, ( void** ) +&theDestBits, 0, 0L ); + + // Copy our source and destination bitmaps onto our DIBSections. + // so we can get access to their bits using the BYTE*'s we used + // in the CreateDIBSection()s above. + + HDC theDC = CreateCompatibleDC( nullptr ); + + HBITMAP theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc ); + + if ( !StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY, +inSourceWidth, inSourceHeight, SRCCOPY ) ) + { + SelectObject( theDC, theDCOld ); + DeleteDC( theDC ); + DeleteObject( theBmpSrc ); + DeleteObject( theBmpDest ); + return false; + } + + SelectObject( theDC, theBmpDest ); + + if (! StretchBlt( theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight, +SRCCOPY ) ) + { + SelectObject( theDC, theDCOld ); + DeleteDC( theDC ); + DeleteObject( theBmpSrc ); + DeleteObject( theBmpDest ); + return true; + } + + SelectObject( theDC, theDCOld ); + DeleteDC( theDC ); + + short theXLoop, theYLoop; + + for( theYLoop=0; theYLoop<inHeight; ++theYLoop ) + { + LPBYTE theDestRGB = ( LPBYTE ) &( ( DWORD* ) theDestBits)[theYLoop * inWidth]; + LPBYTE theSrcRGB = ( LPBYTE ) &( ( DWORD* ) theSrcBits)[theYLoop * inWidth]; + + for( theXLoop=0; theXLoop<inWidth; theXLoop++ ) + { + theSrcRGB[0] = ( BYTE ) ( ( theDestRGB[0] * ( 255 - inAlpha ) + theSrcRGB[0] +* inAlpha ) >> 8 ); + theSrcRGB[1] = ( BYTE ) ( ( theDestRGB[1] * ( 255 - inAlpha ) + theSrcRGB[1] +* inAlpha ) >> 8 ); + theSrcRGB[2] = ( BYTE ) ( ( theDestRGB[2] * ( 255 - inAlpha ) + theSrcRGB[2] +* inAlpha ) >> 8 ); + + theSrcRGB += 4; + theDestRGB += 4; + } + } + + theDC = CreateCompatibleDC( nullptr ); + + theDCOld = ( HBITMAP ) SelectObject( theDC, theBmpSrc ); + + if ( !BitBlt( inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY ) ) + { + SelectObject( theDC, theDCOld ); + DeleteDC( theDC ); + DeleteObject( theBmpSrc ); + DeleteObject( theBmpDest ); + return false; + } + + SelectObject( theDC, theDCOld ); + DeleteDC( theDC ); + + DeleteObject( theBmpSrc ); + DeleteObject( theBmpDest ); + + return true; +}*/ diff --git a/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h new file mode 100644 index 00000000..19cc8f78 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/BufferedRenderer.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_BUFFERED_RENDERER_H +#define INCLUDED_BUFFERED_RENDERER_H 1 + +#pragma once + +#include "WinRenderer.h" + +#include <QPainter> +#include <QPixmap> +#include <QFont> + +class CBufferedRenderer : public CWinRenderer +{ +public: + CBufferedRenderer(const QSize &inSize); + + virtual ~CBufferedRenderer(); + QPixmap pixmap() const override { return m_CurrentBitmap;} + + // void TransparentBltTo( CRenderer* inRenderer, short inAlpha ); + +protected: + QPixmap m_OldBitmap; + QPixmap m_CurrentBitmap; + QSize m_Size; + + // bool AlphaBlendExt( HDC inDCDest, short inX, short inY, short inWidth, short inHeight, HDC + //inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, short inSourceHeight, short + //inAlpha ); +}; +#endif // INCLUDED_BUFFERED_RENDERER_H diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp new file mode 100644 index 00000000..19b263d9 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "MFCEditControl.h" + +//============================================================================== +// Implementation +//============================================================================== + +#ifdef USE_RICHEDIT +IMPLEMENT_DYNAMIC(CMFCEditControl, CRichEditCtrl) +#else +IMPLEMENT_DYNAMIC(CMFCEditControl, CEdit) +#endif + +CMFCEditControl::CMFCEditControl() + : m_Changed(false) + , m_HotKeys(nullptr) +{ +} + +CMFCEditControl::~CMFCEditControl() +{ + // This control's window has been destroyed by PlatformEditControl, + // so a SigTextCommit is potentially dangerous as it will lead to GetText (below) + // which will try to get text from a destroyed window. + // However, if this is needed, note that CEdit works, but CRichEditCtrl don't. + // Can revert to using CEdit by commenting out the line in MFCEditControl.h + + // if ( m_Changed ) + //{ + // m_Changed = false; + // SigTextCommit( ); + //} +} + +Q3DStudio::CString CMFCEditControl::GetText() +{ + Q3DStudio::CString theResult; + +#ifdef USE_RICHEDIT + GETTEXTLENGTHEX getTextLengthEx; + getTextLengthEx.flags = GTL_DEFAULT | GTL_USECRLF; + getTextLengthEx.codepage = 1200; + LRESULT lResult = SendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&getTextLengthEx, 0); + if (lResult > 0) { + GETTEXTEX getTextEx; + getTextEx.cb = (DWORD)(lResult + 2); + getTextEx.codepage = 1200; + getTextEx.flags = GT_DEFAULT | GT_USECRLF; + getTextEx.lpDefaultChar = nullptr; + getTextEx.lpUsedDefChar = nullptr; + wchar_t *ws = new wchar_t[lResult / 2 + 1]; + SendMessage(EM_GETTEXTEX, (WPARAM)&getTextEx, (LPARAM)ws); + theResult = ws; + delete[] ws; + } +#else + ::CString theWindowText; + GetWindowText(theWindowText); + // normal gettext, which depends on machine's locale + theResult = theWindowText; +#endif + + return theResult; +} + +void CMFCEditControl::SetText(const Q3DStudio::CString &inText) +{ + // The text manipulation is actually already being handled by the CEdit/CWnd + // This SetText is called by our custom CPropertyMultilineEdit and screws with the MFC's + // own text handling functions. + // Essentially, we still need this to set up the initial use of the MFC Edit. + if (GetText() == "") { +#ifdef USE_RICHEDIT + SETTEXTEX setTextEx; + setTextEx.codepage = 1200; + setTextEx.flags = ST_DEFAULT; + SendMessage(EM_SETTEXTEX, (WPARAM)&setTextEx, + (LPARAM)(static_cast<const wchar_t *>(inText))); +#else + // normal settext, which depends on machine's locale + SetWindowText(inText.GetMulti()); +#endif + } +} + +#ifdef USE_RICHEDIT +BEGIN_MESSAGE_MAP(CMFCEditControl, CRichEditCtrl) +#else +BEGIN_MESSAGE_MAP(CMFCEditControl, CEdit) +#endif +ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange) +ON_WM_LBUTTONDBLCLK() +ON_WM_SETFOCUS() +ON_WM_KILLFOCUS() +END_MESSAGE_MAP() + +// CMFCEditControl message handlers + +void CMFCEditControl::OnEnChange() +{ + m_Changed = true; + SigTextChanged(); +} + +void CMFCEditControl::OnLButtonDblClk(UINT inSomething, CPoint inPoint) +{ +#ifdef USE_RICHEDIT + CRichEditCtrl::OnLButtonDblClk(inSomething, inPoint); +#else + CEdit::OnLButtonDblClk(inSomething, inPoint); +#endif + + // select all text in this CEdit/CRichEditCtrl + SetSel(0, -1); +} + +void CMFCEditControl::OnSetFocus(CWnd *inWnd) +{ +#ifdef USE_RICHEDIT + CRichEditCtrl::OnSetFocus(inWnd); +#else + CEdit::OnSetFocus(inWnd); +#endif + + m_Changed = false; +} + +void CMFCEditControl::OnKillFocus(CWnd *inWnd) +{ +#ifdef USE_RICHEDIT + CRichEditCtrl::OnKillFocus(inWnd); +#else + CEdit::OnKillFocus(inWnd); +#endif + + if (m_Changed) { + m_Changed = false; + SigTextCommit(); + } +} + +BOOL CMFCEditControl::PreTranslateMessage(MSG *pMsg) +{ + if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) { + // Reserve some keys for Studio's hotkeys + // This is only a subset of Studio's hotkeys as listed in + // CWorkspace::RegisterGlobalKeyboardShortcuts( CHotKeys* inShortcutHandler ) + // We need to make sure that EditControl's hotkeys won't collide with Studio's hotkeys + bool theReservedHotKeys = false; + if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN + || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) { + if (pMsg->wParam >= CHotKeys::KEY_F1 + && pMsg->wParam + <= CHotKeys::KEY_F12) // F1 to F12 keys, this may fail if not in windows + { + theReservedHotKeys = true; + } else if (CHotKeys::IsKeyDown(VK_CONTROL)) { + unsigned int theCharacterCode = ::MapVirtualKey(static_cast<UINT>(pMsg->wParam), 2); + + switch (theCharacterCode) { + case 's': + case 'S': // save file / save file as + case 'o': + case 'O': // open file + case 'n': + case 'N': // new file + theReservedHotKeys = true; + } + } + } + + if (theReservedHotKeys) { + if (m_HotKeys != nullptr) + m_HotKeys->PreTranslateMessage(pMsg); + } else { + // no idea what all that filtering does, since Bug 1695 appears to be working + // and it is causing problem with Japanese text input (2639) + ::TranslateMessage(pMsg); + ::DispatchMessage(pMsg); + } + return TRUE; + + //// This is REALLY bad, but it's basically filtering all the messages that it thinks it + ///might want and handles those. + // if ((::GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0 && (::GetAsyncKeyState(VK_RBUTTON) & + // 0x8000) == 0) + //{ + // unsigned int theChar = pMsg->wParam; + + // /* + // * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39) + // * 0x40 : unassigned + // * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A) + // */ + + // /* + // #define VK_OEM_1 0xBA // ';:' for US + // #define VK_OEM_PLUS 0xBB // '+' any country + // #define VK_OEM_COMMA 0xBC // ',' any country + // #define VK_OEM_MINUS 0xBD // '-' any country + // #define VK_OEM_PERIOD 0xBE // '.' any country + // #define VK_OEM_2 0xBF // '/?' for US + // #define VK_OEM_3 0xC0 // '`~' for US + // #define VK_OEM_4 0xDB // '[{' for US + // #define VK_OEM_5 0xDC // '\|' for US + // #define VK_OEM_6 0xDD // ']}' for US + // #define VK_OEM_7 0xDE // ''"' for US + // #define VK_OEM_8 0xDF + // */ + + // if ( theChar == VK_RETURN || theChar == VK_BACK || theChar == VK_MENU || + // ( theChar >= VK_SPACE && theChar < VK_LWIN ) || + // ( theChar >= VK_OEM_1 && theChar <= VK_OEM_8 ) + // ) + // { + // ::TranslateMessage( pMsg ); + // ::DispatchMessage( pMsg ); + // return TRUE; + // } + //} + } + +#ifdef USE_RICHEDIT + return CRichEditCtrl::PreTranslateMessage(pMsg); +#else + return CEdit::PreTranslateMessage(pMsg); +#endif +} + +BOOL CMFCEditControl::Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID) +{ +// TODO: Add your specialized code here and/or call the base class + +#ifdef USE_RICHEDIT + BOOL theResult = CRichEditCtrl::Create(dwStyle, rect, pParentWnd, nID); + SetEventMask(GetEventMask() | ENM_CHANGE); +#else + BOOL theResult = CEdit::Create(dwStyle, rect, pParentWnd, nID); +#endif + + return theResult; +} diff --git a/src/Authoring/Studio/_Win/Controls/MFCEditControl.h b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h new file mode 100644 index 00000000..9d688fdc --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/MFCEditControl.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "HotKeys.h" + +//============================================================================== +// Class +//============================================================================== + +// RichEditCtrl, though super useful, has some stability issue to be ironed out. +// Use CEdit by commenting out the line below if it is causing crashes. +#define USE_RICHEDIT + +#ifdef USE_RICHEDIT +class CMFCEditControl : public CRichEditCtrl +#else +class CMFCEditControl : public CEdit +#endif +{ +protected: + DECLARE_DYNAMIC(CMFCEditControl) + +public: + boost::signal<void()> SigTextChanged; + boost::signal<void()> SigTextCommit; + +protected: + bool m_Changed; + CHotKeys *m_HotKeys; // global keyboard shortcut (Studio's hotkeys) + +public: + CMFCEditControl(); + virtual ~CMFCEditControl(); + + Q3DStudio::CString GetText(); + void SetText(const Q3DStudio::CString &inText); + + void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys) { m_HotKeys = inHotKeys; } + +protected: + DECLARE_MESSAGE_MAP() +public: + afx_msg void OnEnChange(); + afx_msg void OnLButtonDblClk(UINT, CPoint); + afx_msg void OnSetFocus(CWnd *); + afx_msg void OnKillFocus(CWnd *); + + virtual BOOL PreTranslateMessage(MSG *inMessage); + virtual BOOL Create(DWORD dwStyle, const RECT &rect, CWnd *pParentWnd, UINT nID); +}; diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp new file mode 100644 index 00000000..72a5f17b --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "OffscreenRenderer.h" +#include "AppFonts.h" + +//============================================================================= +/** + * Constructor: Overrides a protected constructor on the base class. Sets up + * all the requirements so that this renderer is valid. + */ +COffscreenRenderer::COffscreenRenderer(const QRect &inClippingRect) + : CWinRenderer() +{ + m_pixmap = QPixmap(inClippingRect.size()); + m_painter = new QPainter(&m_pixmap); + QFont font = CAppFonts::GetInstance()->GetNormalFont(); + m_painter->setFont(font); + + // Set up the specified clipping region. Renderer is now valid for use. + PushClippingRect(inClippingRect); +} + +//============================================================================= +/** + * Destructor + */ +COffscreenRenderer::~COffscreenRenderer() +{ + delete m_painter; + m_painter = nullptr; +} diff --git a/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h new file mode 100644 index 00000000..dccd259f --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/OffscreenRenderer.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_OFFSCREEN_RENDERER_H +#define INCLUDED_OFFSCREEN_RENDERER_H 1 + +//============================================================================== +// Includes +//============================================================================== +#include "WinRenderer.h" + +//============================================================================= +/** + * Class for creating a renderer compatible with the current display, but that + * does not actually draw to the display. Provided so that you controls can + * query text size outside of their draw functions. This class could be + * further extended to provide offscreen drawing and blitting, though it's + * not currently set up to do so. + */ +class COffscreenRenderer : public CWinRenderer +{ +public: + COffscreenRenderer(const QRect &inClippingRect); + virtual ~COffscreenRenderer(); + + QPixmap pixmap() const override { return m_pixmap;} + +protected: + QPixmap m_pixmap; +}; + +#endif // INCLUDED_OFFSCREEN_RENDERER_H diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp new file mode 100644 index 00000000..4c581806 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== +#include "PlatformEditControl.h" +#include "Renderer.h" +#include "StudioPreferences.h" + +#ifdef WIN32 + +CPlatformEditControl::CPlatformEditControl(UICRenderDevice inParent) + : CPlatformWindowControl(inParent) +{ +#ifdef USE_RICHEDIT + BOOL theReturn = m_EditWindow.Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_MULTILINE + | ES_WANTRETURN | ES_AUTOVSCROLL, + CRect(0, 0, 0, 0), CWnd::FromHandle(inParent), 1); +#else + BOOL theReturn = m_EditWindow.CreateEx(0, _T("EDIT"), "", WS_CHILD | WS_VSCROLL | ES_MULTILINE + | ES_WANTRETURN | ES_AUTOVSCROLL, + 0, 0, 0, 0, inParent, nullptr); +#endif + ASSERT(theReturn); + + Q_UNUSED(theReturn); // for release builds + + m_EditWindow.SigTextChanged.connect(std::bind(&CPlatformEditControl::OnTextChanged, this)); + m_EditWindow.SigTextCommit.connect(std::bind(&CPlatformEditControl::OnTextCommit, this)); + + m_Font.CreatePointFont( + 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point + m_EditWindow.SetFont(&m_Font); + m_EditWindow.SetTextMode(TM_PLAINTEXT | TM_MULTILEVELUNDO); + m_EditWindow.SetBackgroundColor(FALSE, CStudioPreferences::GetLightBaseColor()); + + m_Window = m_EditWindow.GetSafeHwnd(); +} + +CPlatformEditControl::~CPlatformEditControl() +{ + m_EditWindow.DestroyWindow(); +} + +//============================================================================= +/** + * Essentially, this just turns the window off. Do not use the CControl::SetVisible + * because that would screw with the control's size and you will notice the inspector + * palette having cut off rows. + * + * @param inIsVisible If the window should be visible + */ +void CPlatformEditControl::SetWindowVisible(bool inIsVisible) +{ + if (inIsVisible) + m_EditWindow.ShowWindow(SW_SHOWNORMAL); + else + m_EditWindow.ShowWindow(SW_HIDE); +} + +void CPlatformEditControl::OnTextChanged() +{ + SigTextChanged(); +} + +void CPlatformEditControl::OnTextCommit() +{ + SigTextCommit(); +} + +void CPlatformEditControl::SetText(const Q3DStudio::CString &inText) +{ + m_EditWindow.SetText(inText); +} + +Q3DStudio::CString CPlatformEditControl::GetText() +{ + return m_EditWindow.GetText(); +} + +void CPlatformEditControl::EnableWindow(bool inEnable) +{ + m_EditWindow.EnableWindow(inEnable); +} + +//============================================================================== +// CControl +//============================================================================== + +void CPlatformEditControl::Draw(CRenderer *inRenderer) +{ + // Create a clipping region for the MFC Edit + CRct theUICClipRect = inRenderer->GetClippingRect(); + RECT theRect(theUICClipRect); + CRgn theClipRgn; + theClipRgn.CreateRectRgnIndirect(&theRect); + HRGN theClipHandle = (HRGN)theClipRgn; + m_EditWindow.SetWindowRgn(theClipHandle, TRUE); + + if (m_EditWindow.IsWindowVisible() == FALSE) + m_EditWindow.ShowWindow(SW_SHOWNORMAL); + + // Draw a bounding box around the entire control + CColor theTopColor = CStudioPreferences::GetControlRectTopLineColor(); + CColor theSideColor = CStudioPreferences::GetControlRectSideLineColor(); + CColor theBottomColor = CStudioPreferences::GetControlRectBottomLineColor(); + + inRenderer->DrawRectOutline(GetSize(), theTopColor, theSideColor, theBottomColor, theSideColor); +} + +#endif // WIN32 diff --git a/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h new file mode 100644 index 00000000..1347b217 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformEditControl.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PLATFORM_EDIT_CONTROL_H +#define INCLUDED_PLATFORM_EDIT_CONTROL_H 1 + +#pragma once + +//============================================================================== +// Include +//============================================================================== +#include "PlatformWindowControl.h" +#include "MFCEditControl.h" + +//============================================================================== +// Class +//============================================================================== + +#ifdef WIN32 + +class CPlatformEditControl : public CPlatformWindowControl +{ +protected: + CFont m_Font; ///< MFC font for the edit text + CMFCEditControl m_EditWindow; ///< MFC Edit Window + +public: + std::signal0<void> SigTextChanged; + std::signal0<void> SigTextCommit; + +public: + CPlatformEditControl(UICRenderDevice inParent); + virtual ~CPlatformEditControl(); + + void SetWindowVisible(bool inIsVisible); + + void SetText(const Q3DStudio::CString &inText); + Q3DStudio::CString GetText(); + void EnableWindow(bool inEnable); + + void SetGlobalKeyboardShortcuts(CHotKeys *inHotKeys) + { + m_EditWindow.SetGlobalKeyboardShortcuts(inHotKeys); + } + + // CControl + virtual void Draw(CRenderer *inRenderer); + +protected: + void OnTextChanged(); + void OnTextCommit(); +}; + +#endif // WIN32 + +#endif // INCLUDED_PLATFORM_EDIT_CONTROL_H diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp new file mode 100644 index 00000000..fc2c2509 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== +#include "PlatformStaticControl.h" + +#ifdef WIN32 + +CPlatformStaticControl::CPlatformStaticControl(UICRenderDevice inParent) + : CPlatformWindowControl(inParent) +{ + BOOL theReturn = m_EditWindow.CreateEx(0, _T("STATIC"), _T(""), WS_VISIBLE | WS_CHILD, 0, 0, 0, + 0, inParent, nullptr); + ASSERT(theReturn); + theReturn; + + m_Font.CreatePointFont( + 80, CString(CStudioPreferences::GetFontFaceName())); // size specified in 1/10ths of a point + m_EditWindow.SetFont(&m_Font); + + m_Window = m_EditWindow.GetSafeHwnd(); +} + +CPlatformStaticControl::~CPlatformStaticControl() +{ + m_EditWindow.DestroyWindow(); +} + +void CPlatformStaticControl::SetText(const Q3DStudio::CString &inText) +{ + m_EditWindow.SetWindowText(inText); +} + +#endif // WIN32
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h new file mode 100644 index 00000000..e8b68fa6 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformStaticControl.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef INCLUDED_PLATFORM_STATIC_CONTROL_H +#define INCLUDED_PLATFORM_STATIC_CONTROL_H 1 + +#pragma once + +//============================================================================== +// Include +//============================================================================== + +#include "PlatformWindowControl.h" + +//============================================================================== +// Class +//============================================================================== + +#ifdef KDAB_TEMPORARILY_REMOVED + +class CPlatformStaticControl : public CPlatformWindowControl +{ +protected: + CFont m_Font; ///< MFC font for the static text + CStatic m_EditWindow; ///< MFC Edit Window + +public: + CPlatformStaticControl(UICRenderDevice inParent); + virtual ~CPlatformStaticControl(); + + void SetText(const Q3DStudio::CString &inText); +}; + +#endif // WIN32 + +#endif // INCLUDED_PLATFORM_STATIC_CONTROL_H diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp new file mode 100644 index 00000000..89279702 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Include +//============================================================================== +#include "PlatformWindowControl.h" + +CPlatformWindowControl::CPlatformWindowControl(UICRenderDevice inParent) + : m_Window(nullptr) +{ + inParent; +} + +CPlatformWindowControl::~CPlatformWindowControl() +{ +} + +//============================================================================== +// CControl +//============================================================================== + +void CPlatformWindowControl::SetPosition(CPt inPosition) +{ + CControl::SetPosition(inPosition); + + CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0)); + + ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); +} + +void CPlatformWindowControl::SetSize(CPt inSize) +{ + CControl::SetSize(inSize); + + ::SetWindowPos(m_Window, nullptr, 0, 0, inSize.x - 2, inSize.y - 2, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOMOVE); +} + +void CPlatformWindowControl::Invalidate(bool inInvalidate) +{ + CControl::Invalidate(inInvalidate); + + // This is neccesary to handle the scroll behavior when + // this item is embedded in a scroll window. + CPt theGlobalPosition = CControl::GetGlobalPosition(CPt(0, 0)); + ::SetWindowPos(m_Window, nullptr, theGlobalPosition.x + 1, theGlobalPosition.y + 1, 0, 0, + SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE); +} + +void CPlatformWindowControl::OnVisibleStateChange(bool inIsVisible) +{ + ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE))); +} + +void CPlatformWindowControl::OnParentVisibleStateChanged(bool inIsVisible) +{ + ::ShowWindow(m_Window, ((inIsVisible) ? (SW_SHOWNORMAL) : (SW_HIDE))); +} + +UICRenderDevice CPlatformWindowControl::GetPlatformDevice() +{ + return m_Window; +} diff --git a/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h new file mode 100644 index 00000000..f76697f6 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/PlatformWindowControl.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef INCLUDED_PLATFORM_WINDOW_CONTROL_H +#define INCLUDED_PLATFORM_WINDOW_CONTROL_H 1 + +#pragma once + +//============================================================================== +// Include +//============================================================================== + +#include "Control.h" + +//============================================================================== +// Class +//============================================================================== + +class CPlatformWindowControl : public CControl +{ +protected: + UICRenderDevice m_Window; ///< + +public: + CPlatformWindowControl(UICRenderDevice inParent); + virtual ~CPlatformWindowControl(); + + // CControl + void SetPosition(CPt inPosition) override; + void SetSize(CPt inSize) override; + void Invalidate(bool inInvalidate = true) override; + + void OnVisibleStateChange(bool inIsVisible) override; + void OnParentVisibleStateChanged(bool inIsVisible) override; + + UICRenderDevice GetPlatformDevice() override; +}; + +#endif // INCLUDED_PLATFORM_WINDOW_CONTROL_H diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp new file mode 100644 index 00000000..3b9cddf1 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.cpp @@ -0,0 +1,525 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stdafx.h" + +#include "WinRenderer.h" +#include "MasterP.h" +#include <math.h> +#include "CoreUtils.h" + +//============================================================================= +/** + * Leaves the Renderer in an invalid state, only for subclasses. + * In order for this renderer to be valid, you must do two things: (1) you must + * create a CDC and set m_DC equal to it, and (2) you must call PushClippingRect. + */ +CWinRenderer::CWinRenderer() + : m_painter(nullptr) +{ +} + +//============================================================================= +/** + * Leaves the Renderer in an invalid state, only for subclasses. + * PushClippingRect must be called in order for this to become valid. + */ +CWinRenderer::CWinRenderer(QPainter *inDC) +{ + m_painter = inDC; +} + +CWinRenderer::CWinRenderer(QPainter *inDC, const QRect &inClippingRect) +{ + m_painter = inDC; + + PushClippingRect(inClippingRect); +} + +CWinRenderer::~CWinRenderer() +{ + m_Pens.clear(); +} + +//============================================================================= +/** + * Draws a rectangle and fills it with inColor. + * The rectangle has no border and is solid. + * The coordinates are converted to global space using the current translation. + * @param inCoordinates the coordinates of the rectangle. + * @param inColor the color of the rectangle to draw. + */ +void CWinRenderer::FillSolidRect(const QRect &inCoordinates, const QColor &inColor) +{ + QRect theRect(inCoordinates.topLeft() + m_Translation, + inCoordinates.size()); + + m_painter->fillRect(theRect, inColor); +} + +//============================================================================= +/** + * Move the pen to the position. + * This will put the pen at inPoint but will not draw a line there from the + * current location. + * @param inPoint the location to move to, in local coordinates. + */ +void CWinRenderer::MoveTo(const QPoint &inPoint) +{ + m_currentPos = inPoint + m_Translation; +} + +//============================================================================= +/** + * Move the pen to the position. + * This will put the pen to the point but will not draw a line there from the + * current location. + * @param inX the X location to move to, in local coordinates. + * @param inY the Y location to move to, in local coordinates. + */ +void CWinRenderer::MoveTo(long inX, long inY) +{ + MoveTo(QPoint(inX, inY)); +} + +//============================================================================= +/** + * Draw a line from the current pen location to inPoint. + * This will draw a line to inPoint and move the current location of the pen + * to inPoint. + * @param inPoint the location to draw to, in local coordinates. + */ +void CWinRenderer::LineTo(const QPoint &inPoint) +{ + const QPoint point = inPoint + m_Translation; + m_painter->drawLine(m_currentPos, point); + m_painter->drawLine(point, QPoint(point.x(), point.y() + 1)); + m_currentPos = point; +} + +//============================================================================= +/** + * Draw a line from the current pen location to the point. + * This will draw a line to the point and move the current location of the pen + * to inPoint. + * @param inX the X coordinate of the point to draw to, in local coordinates. + * @param inY the Y coordinate of the point to draw to, in local coordinates. + */ +void CWinRenderer::LineTo(long inX, long inY) +{ + LineTo(QPoint(inX, inY)); +} + +//============================================================================= +/** + * Change the active pen color. + * This acts as a stack so that it does not interfere with previous components. + * Once the color is done being used PopPen should be called. + * @param inColor the color to make the current pen. + * @param inWidth the pen width, in pixels. + */ +void CWinRenderer::PushPen(const QColor &inColor, int inWidth) +{ + QPen thePen = GetPen(inColor, inWidth, Qt::SolidLine); + + QPen theCurrentPen = m_painter->pen(); + m_painter->setPen(thePen); + m_PenList.push_back(theCurrentPen); +} + +void CWinRenderer::PopPen() +{ + QPen thePen = m_PenList.back(); + m_PenList.pop_back(); + m_painter->setPen(thePen); +} + +//============================================================================= +/** + * Copy the bits from another renderer into this one. + * This will copy the rect from inRenderer into this renderer. + * inRect will be offset by this renderer's current translation. inXSrc and inYSrc + * will be offset by inRenderer's current translation. + * @param inRect the position and size of the area to be copied into this renderer. + * @param inPixmap the renderer to copy from. + * @param xSrc the x location of the location to copy from in inRenderer. + * @param ySrc the y location of the location to copy from in inRenderer. + */ +void CWinRenderer::BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc) +{ + const auto inTranslation = inRenderer->GetTranslation(); + inXSrc += inTranslation.x(); + inYSrc += inTranslation.y(); + + auto srcRect = inRect; + auto destRect = inRect; + destRect.translate(m_Translation); + srcRect.moveTo(inXSrc, inYSrc); + m_painter->save(); + m_painter->setCompositionMode(QPainter::CompositionMode_DestinationOver); + m_painter->drawPixmap(destRect, inRenderer->pixmap(), srcRect); + m_painter->restore(); +} + +//============================================================================= +/** + * Draws text out without clipping it. + * @param inPoint the point at which to draw the text. (upper left corner) + * @param inText the text to draw. + */ +void CWinRenderer::DrawText(float inX, float inY, const QString &inText) +{ + inX += m_Translation.x(); + inY += m_Translation.y(); + m_painter->drawText(QPointF(inX, inY), inText); +} + +//============================================================================= +/** + * Draws text out to a clipped rectangle. + * If any text occurs outside the bounding box then it will be clipped. + * @param inPoint the point at which to draw the text. (upper left corner) + * @param inText the text to draw. + * @param inBoundingBox the bounding box used to clip the text. + * @param inColor color to draw the text in + */ +void CWinRenderer::DrawText(float inX, float inY, const QString &inText, + const QRect &inBoundingBox, const QColor &inColor) +{ + inX += m_Translation.x(); + inY += m_Translation.y(); + + QRectF rect(inBoundingBox); + rect.translate(inX, inY); + m_painter->save(); + QPen pen(inColor); + m_painter->setPen(pen); + m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText); + m_painter->restore(); +} + +//============================================================================= +/** + * Draws BOLD text out to a clipped rectangle. + * If any text occurs outside the bounding box then it will be clipped. + * @param inPoint the point at which to draw the text. (upper left corner) + * @param inText the text to draw. + * @param inBoundingBox the bounding box used to clip the text. + * @param inColor color to draw the text in + */ +void CWinRenderer::DrawBoldText(float inX, float inY, const QString &inText, + const QRect &inBoundingBox, const QColor &inColor) +{ + inX += m_Translation.x(); + inY += m_Translation.y(); + + QRectF rect(inBoundingBox); + rect.translate(inX, inY); + m_painter->save(); + QPen pen(inColor); + m_painter->setPen(pen); + QFont font = m_painter->font(); + font.setBold(true); + m_painter->setFont(font); + m_painter->drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, inText); + m_painter->restore(); +} + +//============================================================================= +/** + * Gets the dimensions of the text string as it would be written out to the + * screen. + * @param inText the text to check the length on. + * @return the length of the text in pixels. + */ +QSize CWinRenderer::GetTextSize(const QString &inText) +{ + QFontMetrics fm = m_painter->fontMetrics(); + return fm.size(Qt::TextSingleLine, inText); +} + +//============================================================================= +/** + * Draws a a three-dimensional rectangle with the top and left sides in the + * color specified by inTopLeftColor and the bottom and right sides in the color + * specified by inBottomRightColor. + * + * @param inRect The rectangle to draw + * @param inTopLeftColor Color for the top and left sides of the rect + * @param inBottomRightColor Color for the bottom and right sides of the rect + */ +void CWinRenderer::Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor, + const QColor &inBottomRightColor) +{ + auto rect = inRect; + rect.translate(m_Translation); + m_painter->drawRect(rect); + m_painter->save(); + m_painter->setPen(inTopLeftColor); + m_painter->drawLine(rect.topLeft(), rect.bottomLeft()); + m_painter->drawLine(rect.topLeft(), rect.topRight()); + m_painter->setPen(inBottomRightColor); + m_painter->drawLine(rect.bottomLeft(), rect.bottomRight()); + m_painter->drawLine(rect.bottomRight(), rect.topRight()); + m_painter->restore(); +} + +//============================================================================== +/** + * DrawBitmap + * + * Draw a bitmap given a device context, position and HBITMAP handle. + * + * @param inDC Device context for drawing + * @param inPos CPoint position for drawing + * @param inBitmap Handle of the bitmap to draw + */ +//============================================================================== +void CWinRenderer::DrawBitmap(const QPoint &inPos, const QPixmap &inImage) +{ + m_painter->save(); + m_painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + m_painter->drawPixmap(inPos + m_Translation, inImage); + m_painter->restore();; +} + +void CWinRenderer::PushTranslation(const QPoint &inTranslation) +{ + m_Translation += inTranslation; + + m_Translations.push_back(inTranslation); +} + +void CWinRenderer::PopTranslation() +{ + QPoint thePreviousTranslation = m_Translations.back(); + m_Translation -= thePreviousTranslation; + + m_Translations.pop_back(); +} + +QPoint CWinRenderer::GetTranslation() +{ + return m_Translation; +} + +QPainter* CWinRenderer::GetPainter() +{ + return m_painter; +} + +//============================================================================== +/** + * Get the current clipping rect. + * The clipping rect is the boundary of pixels that will be drawn to the DC. + * This can be used to not draw non-visible objects. + * @return the clipping rect in local coordinates. + */ +QRect CWinRenderer::GetClippingRect() +{ + QRect theClippingRect = m_painter->clipBoundingRect().toRect(); + theClippingRect.translate(-m_Translation); + + return theClippingRect; +} + +//============================================================================== +/** + * Push a clipping rect onto the stack of clipping rects. + * This will cause any drawing outside of the clipping rect to be ignored. The + * Control class also uses this to not draw objects outside of this rect. + * @param inClippingRect the new clipping rect, in local coordinates. + */ +void CWinRenderer::PushClippingRect(const QRect &inClippingRect) +{ + QRect clippingRect(inClippingRect); + clippingRect.translate(m_Translation); + + const QRegion currentRegion = m_painter->clipRegion(); + m_painter->setClipRect(clippingRect); + + m_ClippingRegions.push_back(currentRegion); +} + +//============================================================================== +/** + * Pop the current clipping rect. + * This will change the clipping rect to use the one previous to the current + * one. + */ +void CWinRenderer::PopClippingRect() +{ + if (m_ClippingRegions.size() > 1) { + QRegion thePreviousRegion = m_ClippingRegions.back(); + m_painter->setClipRegion(thePreviousRegion); + m_ClippingRegions.pop_back(); + } +} + +//============================================================================== +/** + * DrawGradiantBitmap + * + * Draws a gradiant based on the begin color + * + * @param inRct Rct tof the control + * @param inBeginColor color to start with + * @param inInverted true if this is inverted + */ +void CWinRenderer::DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted, + double inScalingFactor) +{ + QRect rect(inRct); + QRect theClippingRect = GetClippingRect(); + rect &= theClippingRect; + rect.translate(m_Translation); + + long theHeight = rect.height(); + long theWidth = rect.width(); + + QImage theCompatibleBitmap(1, theHeight, QImage::Format_RGB32); + + int theR = inBeginColor.red(); + int theG = inBeginColor.green(); + int theB = inBeginColor.blue(); + + double theExtraRModifier = inScalingFactor * (1.0 - (theR / 255.0)); + double theExtraGModifier = inScalingFactor * (1.0 - (theG / 255.0)); + double theExtraBModifier = inScalingFactor * (1.0 - (theB / 255.0)); + + for (long thePixel = 0; thePixel < theHeight; ++thePixel) { + double theNormPixel = (double)thePixel / (theHeight * 4.8); + double theCos = 1.0 / (theNormPixel * theNormPixel + 1.0); + double theRValue = (double)theR * (theCos + theExtraRModifier); + double theGValue = (double)theG * (theCos + theExtraGModifier); + double theBValue = (double)theB * (theCos + theExtraBModifier); + + QColor theTempColor(::dtoi(theRValue), ::dtoi(theGValue), ::dtoi(theBValue)); + if (inInverted) { + theCompatibleBitmap.setPixelColor(0, qMax(0l, theHeight - thePixel - 2), theTempColor); + } else { + theCompatibleBitmap.setPixelColor(0, thePixel, theTempColor); + } + theExtraRModifier *= 0.3; + theExtraGModifier *= 0.3; + theExtraBModifier *= 0.3; + } + + m_painter->save(); + m_painter->drawImage(QRect(rect.x(), rect.y(), theWidth, theHeight), theCompatibleBitmap); + m_painter->restore(); +} + +//============================================================================= +/** + * Scroll the selected area of the current view by the specified amount. + * This will take the rectangle represented by inVisibleSize and 'scroll' it + * by inAmount. The section that goes out of the visible size will be clipped + * off and the area entering the visible area will be empty. + * @param inAmount the amount to scroll by. + * @param inVisibleSize the rectangle to be scrolled. + * @return the smallest rect of area that needs to be redrawn. + */ +QRect CWinRenderer::Scroll(const QPoint &inAmount, const QRect &inVisibleSize) +{ +#if KDAB_TEMPORARILY_REMOVED + inAmount.Offset(m_Translation); + inVisibleSize.Offset(m_Translation); + + QRect theVisibleRect(QPoint(inVisibleSize.position.x, inVisibleSize.position.y), + QSize(inVisibleSize.size.x, inVisibleSize.size.y)); + + CRgn theDirtyRegion; + CRect theDirtyRect; + m_painter->ScrollDC(inAmount.x, inAmount.y, theVisibleRect, theVisibleRect, &theDirtyRegion, + &theDirtyRect); + + QRect theDirtyRct(theDirtyRect.left, theDirtyRect.top, theDirtyRect.right - theDirtyRect.left, + theDirtyRect.bottom - theDirtyRect.top); + + theDirtyRct.Offset(QPoint(-m_Translation.x, -m_Translation.y)); + + return theDirtyRct; +#else + return {}; +#endif +} + +//============================================================================= +/** + * Draw a gradient over inRect. + * This will blend horizontally across the rect from inBeginColor into inEndColor. + * This does linear interpolation. + * @param inRect the rect to draw on. + * @param inBeginColor the start (left most) color. + * @param inEndColor the final (right most) color. + */ +void CWinRenderer::DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor) +{ + const QRect rect = inRect.translated(m_Translation); + QLinearGradient gradient(rect.topLeft(), rect.topRight()); + gradient.setColorAt(0, inBeginColor); + gradient.setColorAt(1, inEndColor); + + QBrush brush(gradient); + m_painter->fillRect(rect, brush); +} + +void CWinRenderer::FillHashed(const QRect &inRect, const QColor &inForegroundColor) +{ + m_painter->save(); + + QBrush theBrush(inForegroundColor, Qt::BDiagPattern); + QPen pen(inForegroundColor); + m_painter->setPen(pen); + m_painter->setBrush(theBrush); + m_painter->drawRect(inRect.translated(m_Translation)); + + m_painter->restore(); +} + +QPen CWinRenderer::GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle) +{ + QPen thePen; + SPenInfo theInfo = { inColor, inWidth, inStyle }; + TPenMap::iterator thePos = m_Pens.find(theInfo); + if (thePos != m_Pens.end()) { + thePen = thePos->second; + } else { + thePen.setColor(inColor); + thePen.setWidth(inWidth); + m_Pens[theInfo] = thePen; + } + return thePen; +} + +QPixmap CWinRenderer::pixmap() const +{ + return {}; +} diff --git a/src/Authoring/Studio/_Win/Controls/WinRenderer.h b/src/Authoring/Studio/_Win/Controls/WinRenderer.h new file mode 100644 index 00000000..4ebcc689 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/WinRenderer.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_WIN_RENDERER_H +#define INCLUDED_WIN_RENDERER_H 1 + +#pragma once + +#include <vector> +#include <map> + +#include "Pt.h" +#include "Rct.h" +#include "Renderer.h" + +#include <QPainter> +#include <QRegion> + +QT_BEGIN_NAMESPACE +class QPixmap; +QT_END_NAMESPACE + +class CWinRenderer : public CRenderer +{ + typedef std::vector<QPen> TPenList; + typedef std::vector<QRegion> TClippingRegions; + +protected: + CWinRenderer(); ///< Leaves CRenderer in an invalid state, only for subclasses + CWinRenderer(QPainter *inDC); ///< Leaves CRenderer in an invalid state, only for subclasses + +public: + CWinRenderer(QPainter *inDC, const QRect &inClippingRect); + virtual ~CWinRenderer(); + + void FillSolidRect(const QRect &inCoordinates, const QColor &inColor) override; + + void MoveTo(const QPoint &inPoint) override; + void MoveTo(long inX, long inY) override; + void LineTo(const QPoint &inPoint) override; + void LineTo(long inX, long inY) override; + + void PushPen(const QColor &inColor, int inWidth = 1) override; + void PopPen() override; + void BitBltFrom(const QRect &inRect, CRenderer *inRenderer, long inXSrc, long inYSrc) override; + + void DrawText(float inX, float inY, const QString &inText) override; + void DrawText(float inX, float inY, const QString &inText, + const QRect &inBoundingRect, const QColor &inColor = Qt::black) override; + void DrawBoldText(float inX, float inY, const QString &inText, + const QRect &inBoundingRect, const QColor &inColor = Qt::black) override; + + QSize GetTextSize(const QString &inText) override; + + void DrawBitmap(const QPoint &inPos, const QPixmap &inImage) override; + void Draw3dRect(const QRect &inRect, const QColor &inTopLeftColor, + const QColor &inBottomRightColor) override; + void DrawGradientBitmap(const QRect &inRct, const QColor &inBeginColor, bool inInverted, + double inScalingFactor = .99) override; + + void DrawGradient(const QRect &inRect, const QColor &inBeginColor, const QColor &inEndColor) override; + + void PushTranslation(const QPoint &inTranslation) override; + void PopTranslation() override; + QPoint GetTranslation() override; + + QRect GetClippingRect() override; + void PushClippingRect(const QRect &inRect) override; + void PopClippingRect() override; + void PushAbsoluteClippingRect(const QRect &inRect) override {} + void FillHashed(const QRect &inRect, const QColor &inForeGroundColor) override; + QRect Scroll(const QPoint &inAmount, const QRect &inVisibleSize) override; + QPainter *GetPainter() override; + QPen GetPen(const QColor &inColor, int inWidth, Qt::PenStyle inStyle); + + QPixmap pixmap() const override; + +protected: + TPenList m_PenList; + TClippingRegions m_ClippingRegions; + QPainter *m_painter; + QPoint m_currentPos; + +protected: + struct SPenInfo + { + QColor Color; + long Width; + Qt::PenStyle Style; + }; + + class CPenInfoLessThan : public std::binary_function<const SPenInfo &, const SPenInfo &, bool> + { + public: + inline bool operator()(const SPenInfo &inValL, const SPenInfo &inValR) const + { + return memcmp(&inValL, &inValR, sizeof(SPenInfo)) < 0; + } + }; + + typedef std::map<SPenInfo, QPen, CPenInfoLessThan> TPenMap; + TPenMap m_Pens; +}; +#endif // INCLUDED_WIN_RENDERER_H diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.cpp b/src/Authoring/Studio/_Win/Controls/WndControl.cpp new file mode 100644 index 00000000..c218f9b9 --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/WndControl.cpp @@ -0,0 +1,1006 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stdafx.h" + +#include "WndControl.h" +#include "WinRenderer.h" +#include "Control.h" +#include "MasterP.h" +#include "AppFonts.h" +#include "ContextMenu.h" +#include "HotKeys.h" +#include "StudioPreferences.h" +#include "WinDnd.h" +#include "Doc.h" +#include "DropSource.h" +#include "IDragable.h" +#include "OffscreenRenderer.h" + +BEGIN_MESSAGE_MAP(CWndControl, CWnd) +//{{AFX_MSG_MAP(CWndControl) +ON_WM_KILLFOCUS() +ON_WM_SETFOCUS() +ON_WM_PAINT() +ON_WM_LBUTTONUP() +ON_WM_LBUTTONDOWN() +ON_WM_RBUTTONDOWN() +ON_WM_RBUTTONUP() +ON_WM_LBUTTONDBLCLK() +ON_WM_SIZING() +ON_WM_ERASEBKGND() +ON_WM_SIZE() +ON_WM_MOUSEMOVE() +ON_WM_CREATE() +ON_WM_MOUSEACTIVATE() +ON_WM_MOUSEWHEEL() +ON_WM_CTLCOLOR() +ON_CONTROL_REFLECT(EN_CHANGE, OnEnChange) +//}}AFX_MSG_MAP +ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) +ON_MESSAGE(WM_MOUSEHOVER, OnMouseHover) +END_MESSAGE_MAP() + +//============================================================================= +/** + * Creates the pass thru class for the wnd control. + */ +CWndControlControlListener::CWndControlControlListener(CWndControl *inParent) +{ + m_Parent = inParent; +} + +//============================================================================= +/** + * Notification from the control that the window was invalidated. + */ +void CWndControlControlListener::OnControlInvalidated() +{ + m_Parent->OnControlInvalidated(); +} + +//============================================================================= +/** + * Notification from the control to do a popup at the specified location. + */ +long CWndControlControlListener::DoPopup(CContextMenu *inContextMenu, CPt inPoint) +{ + return m_Parent->DoPopup(inContextMenu, inPoint); +} + +//============================================================================= +/** + * Get the location of the point in Screen coordinates. + */ +CPt CWndControlControlListener::ClientToScreen(CPt inPoint) +{ + CPoint thePoint(inPoint.x, inPoint.y); + m_Parent->ClientToScreen(&thePoint); + + return CPt(thePoint.x, thePoint.y); +} + +//============================================================================= +/** + * Get the location of the point into client coordinates. + */ +CPt CWndControlControlListener::ScreenToClient(CPt inPoint) +{ + CPoint thePoint(inPoint.x, inPoint.y); + m_Parent->ScreenToClient(&thePoint); + + return CPt(thePoint.x, thePoint.y); +} + +//============================================================================= +/** + * Get the platform dependent view that this is embedding. + * Used when platform dependent controls need to be embedded into the Controls. + */ +TPlatformView CWndControlControlListener::GetPlatformView() +{ + return m_Parent->m_hWnd; +} + +//============================================================================= +/** + * Pass-thru to the CWndControl's SetIsDragging function. + * @param inIsDragging true to specify that a drag is occurring or false to cancel a drag + */ +void CWndControlControlListener::SetIsDragging(bool inIsDragging) +{ + m_Parent->SetIsDragging(inIsDragging); +} + +//============================================================================= +/** + * Pass-thru to the CWndControl's ShowTooltips function. + * @param inLocation mid-point of the tooltip in global coordinates + * @param inText text to display as a tooltip + */ +void CWndControlControlListener::ShowTooltips(CPt inLocation, Q3DStudio::CString inText) +{ + m_Parent->ShowTooltips(inLocation, inText); +} + +//============================================================================= +/** + * Pass-thru to the CWndControl's HideTooltips function. + */ +void CWndControlControlListener::HideTooltips() +{ + m_Parent->HideTooltips(); +} + +//============================================================================= +/** + * Pass-thru to the CWndControl's ShowMoveableTooltips function. + * @param inLocation mid-point of the tooltip in global coordinates + * @param inText text to display as a tooltip + */ +void CWndControlControlListener::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, + CRct inBoundingRct) +{ + m_Parent->ShowMoveableWindow(inLocation, inText, inBoundingRct); +} + +//============================================================================= +/** + * Pass-thru to the CWndControl's HideMoveableTooltips function. + */ +void CWndControlControlListener::HideMoveableWindow() +{ + m_Parent->HideMoveableWindow(); +} + +void CWndControlControlListener::DoStartDrag(IDragable *inDragable) +{ + m_Parent->DoStartDrag(inDragable); +} + +//=============================================================================== +/** +* performs a drag operation on a file +*/ +void CWndControlControlListener::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList) +{ + m_Parent->DoStartDrag(inDragFileNameList); +} + +IMPLEMENT_OBJECT_COUNTER(CWndControl); + +//============================================================================== +/** + * Constructor + */ +CWndControl::CWndControl(CControl *inControl) + : m_MouseOver(false) + , m_MemDC(nullptr) + , m_IsDragging(false) + , m_ControlListener(this) + , m_IsMouseDown(false) +{ + ADDTO_OBJECT_COUNTER(CWndControl); + + m_Control = inControl; + + if (m_Control) + m_Control->SetWindowListener(&m_ControlListener); + + RegisterWindowClass(); + + // Create the tooltip for this window (there's only one per view) + m_Tooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS), L"CPopupWndTooltip", + WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this, 0); + m_Tooltip.SetStationary(true); + + // Create the tooltip for this window (there's only one per view) + m_MoveableTooltip.CreateEx(WS_EX_TOOLWINDOW, AfxRegisterWndClass(CS_SAVEBITS), + L"CPopupWndTooltip", WS_POPUP | WS_BORDER, CRect(0, 0, 20, 10), this, + 0); + m_MoveableTooltip.SetStationary(false); + + m_Brush.CreateSolidBrush(CStudioPreferences::GetBaseColor()); + +#ifdef _DEBUG + m_IsPainting = false; +#endif +} + +//============================================================================== +/** + * Destructor + */ +CWndControl::~CWndControl() +{ + DeleteBuffers(); + + REMOVEFROM_OBJECT_COUNTER(CWndControl); +} + +// Register the window class if it has not already been registered. +BOOL CWndControl::RegisterWindowClass() +{ + WNDCLASS wndcls; + HINSTANCE hInst = AfxGetInstanceHandle(); + + if (!(::GetClassInfo(hInst, WNDCONTROL_CLASSNAME, &wndcls))) { + // otherwise we need to register a new class + wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; + wndcls.lpfnWndProc = ::DefWindowProc; + wndcls.cbClsExtra = wndcls.cbWndExtra = 0; + wndcls.hInstance = hInst; + wndcls.hIcon = nullptr; + wndcls.hCursor = nullptr; + wndcls.hbrBackground = m_Brush; + wndcls.lpszMenuName = nullptr; + wndcls.lpszClassName = WNDCONTROL_CLASSNAME; + + if (!AfxRegisterClass(&wndcls)) { + AfxThrowResourceException(); + return FALSE; + } + } + + return TRUE; +} + +//============================================================================== +/** + * Create: Handles the WM_CREATE message. + * + * Creates the view, sets the font, and loads the toolbar. + * + * @param lpszClassName Names the Windows class. The class name can be any name + *registered with the AfxRegisterWndClass + * @param lpszWindowName Represents the window name. Used as text for the title bar. + * @param dwStyle Specifies the window style attributes. + * @param rect Specifies the size and position of the window. + * @param pParentWnd Pointer to the parent of the view. + * @param nID The ID for the view. + * @param pContext Create context for the view. + * + * @return TRUE if creation was successful, otherwise FALSE. + */ +//============================================================================== +int CWndControl::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + return CWnd::OnCreate(lpCreateStruct); +} + +//============================================================================= +/** + * MFC notification that this window needs to be redrawn. + * This buffers the draw DC, makes a Renderer and has the Control draw to the + * buffered DC. + */ +void CWndControl::OnPaint() +{ +#ifdef _DEBUG + m_IsPainting = true; +#endif + + UICPROFILE(OnPaint); + + CPaintDC dc(this); + + HDC theDeviceContext = dc.GetSafeHdc(); + + RECT theSize; + this->GetClientRect(&theSize); + + bool theRedrawAllFlag = false; + + if (m_MemDC == nullptr) { + m_MemDC = new CDC(); + m_MemDC->CreateCompatibleDC(&dc); + m_MemDC->SelectObject(CAppFonts::GetInstance()->GetNormalFont()); + + m_MemBitmap = ::CreateCompatibleBitmap(theDeviceContext, theSize.right, theSize.bottom); + + m_OldBitmap = (HBITMAP)m_MemDC->SelectObject(m_MemBitmap); + + theRedrawAllFlag = true; + } + + CRct theDirtyRect; + { + UICPROFILE(OnPaint_Render); + CWinRenderer theRenderer(m_MemDC, CRct(0, 0, theSize.right, theSize.bottom)); + if (m_Control) + m_Control->OnDraw(&theRenderer, theDirtyRect, theRedrawAllFlag); + } + + // Copy (BitBlt) bitmap from bitmap memory DC to memory DC + // ::BitBlt( theDeviceContext, theDirtyRect.position.x, theDirtyRect.position.y, + //theDirtyRect.size.x, theDirtyRect.size.y, m_MemDC->GetSafeHdc( ), theDirtyRect.position.x, + //theDirtyRect.position.y, SRCCOPY ); + ::BitBlt(theDeviceContext, 0, 0, theSize.right, theSize.bottom, m_MemDC->GetSafeHdc(), 0, 0, + SRCCOPY); + +#ifdef _DEBUG + m_IsPainting = false; +#endif +} + +void CWndControl::DeleteBuffers() +{ + if (m_MemDC != nullptr) { + m_MemDC->SelectObject(m_OldBitmap); + ::DeleteObject(m_MemBitmap); + m_MemDC->DeleteDC(); + delete m_MemDC; + m_MemDC = nullptr; + } +} + +//============================================================================= +/** + * Notification to this window that it has lost focus. + * @param pNewWnd the window that has gained focus. + */ +void CWndControl::OnKillFocus(CWnd *pNewWnd) +{ + CWnd::OnKillFocus(pNewWnd); + + // This is used for special cases where we lose control of the mouse and lose focus as well. + // It makes sure we are not still receiving mouse messages. + if (m_IsMouseDown) { + // Tell the control that it got a mouse up + if (m_Control) + m_Control->OnMouseUp(CPt(-1, -1), CHotKeys::GetCurrentKeyModifiers()); + ReleaseCapture(); + } + + if (m_Control) { + // For the case where pNewWnd is an "embedded" control in m_Control (eg. + // CPlatformEditControl) + // m_Control should not lose focus. + // Note that since most of the Studio controls uses a common PlatformDevice (the Studio + // window), + // this (OnKillFocus) only occurs when 1) switching to another app, 2) popping up a dialog + // box or 3) an embedded control + // takes focus. + // This takes care of the case when an embedded control takes focus but unwittingly causes + // its parent to lose focus. + // This can have dire consequences if the parent control were to do something on losing + // focus, such as + // destroying all its children. For example, Bug3421. + if (!m_Control->IsChildPlatformDevice(pNewWnd->GetSafeHwnd())) + m_Control->OnLoseFocus(); + } +} + +void CWndControl::OnSetFocus(CWnd *pPrevWnd) +{ + CWnd::OnSetFocus(pPrevWnd); + if (m_Control) + m_Control->OnGainFocus(); +} + +//============================================================================= +/** + * Notification of mouse up. + */ +void CWndControl::OnLButtonUp(UINT nFlags, CPoint inPoint) +{ + Q_UNUSED(nFlags); + m_IsMouseDown = false; + // Tell the control that it got a mouse up + if (m_Control) + m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers()); + + ReleaseCapture(); + + CWnd::OnLButtonUp(nFlags, inPoint); +} + +//============================================================================= +/** + * Notification of a mouse click. + */ +void CWndControl::OnLButtonDown(UINT nFlags, CPoint inPoint) +{ + Q_UNUSED(nFlags); + m_IsMouseDown = true; + SetCapture(); + // Tell the control that it got a mouse down. + if (m_Control) + m_Control->OnMouseDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers()); + + CWnd::OnLButtonDown(nFlags, inPoint); +} + +//============================================================================= +/** + * Notification of a mouse click. + */ +void CWndControl::OnRButtonDown(UINT nFlags, CPoint inPoint) +{ + SetCapture(); + + if (m_IsMouseDown) { + // Tell the control that it got a mouse up + if (m_Control) + m_Control->OnMouseUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers()); + m_IsMouseDown = false; + } + + // Tell the control that it got a mouse down. + if (m_Control) + m_Control->OnMouseRDown(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers()); + + CWnd::OnRButtonDown(nFlags, inPoint); +} + +//============================================================================= +/** + * Notification of mouse up. + */ +void CWndControl::OnRButtonUp(UINT nFlags, CPoint inPoint) +{ + Q_UNUSED(nFlags); + + // Tell the control that it got a mouse up + if (m_Control) + m_Control->OnMouseRUp(CPt(inPoint.x, inPoint.y), CHotKeys::GetCurrentKeyModifiers()); + + ReleaseCapture(); +} + +long CWndControl::DoPopup(CContextMenu *inMenu, CPt inPoint) +{ + CPoint thePoint(inPoint.x, inPoint.y); + ClientToScreen(&thePoint); + + long theSelectedItem = inMenu->DoPopup(CPt(thePoint.x, thePoint.y), m_hWnd); + if (m_IsMouseDown) { + m_IsMouseDown = false; + if (m_Control) + m_Control->OnMouseUp(CPt(-1, -1), 0); + } + ReleaseCapture(); + + return theSelectedItem; +} + +//============================================================================= +/** + * Notification of a mouse double click. + */ +void CWndControl::OnLButtonDblClk(UINT nFlags, CPoint inPoint) +{ + Q_UNUSED(nFlags); + + // Tell the control that it got a mouse down. + if (m_Control) + m_Control->OnMouseDoubleClick(CPt(inPoint.x, inPoint.y), nFlags); +} + +//============================================================================= +/** + * Notification of a key down message. + */ +bool CWndControl::OnKeyDown(UINT inChar, UINT, UINT) +{ + return m_Control->OnKeyDown(inChar, CHotKeys::GetCurrentKeyModifiers()); +} + +//============================================================================= +/** + * Notification of a key up messages. May be hooked up later. + */ +bool CWndControl::OnKeyUp(UINT inChar, UINT, UINT) +{ + return m_Control->OnKeyUp(inChar, CHotKeys::GetCurrentKeyModifiers()); +} + +//============================================================================= +/** + * Notification of a character press message. + * + * @return true if the character was processed by the control, otherwise false + */ +bool CWndControl::OnChar(UINT inChar, UINT, UINT) +{ + return m_Control->OnChar(inChar, CHotKeys::GetCurrentKeyModifiers()); +} + +//============================================================================= +/** + * Displays a tooltip at the desired location, and with the desired text. + * @param inLocation mid-point of the tooltext message box to be displayed + * @param inText text to be displayed as the tooltip + */ +void CWndControl::ShowTooltips(CPt inLocation, Q3DStudio::CString inText) +{ + // If the global preference for tooltips is enabled + if (CStudioPreferences::ShouldShowTooltips()) { + // If the tooltip text is not empty, show the tooltip + if (!inText.IsEmpty()) { + // So that tooltip text renders within the window + // this would be nicely taken care of if this were a MFC control... + COffscreenRenderer theOffscreenRenderer(CRct(0, 0, 1, 1)); + float theWidth(0); + float theHeight(0); + theOffscreenRenderer.GetTextSize(inText, theWidth, theHeight); + + long theRightMargin = m_Control->GetPosition().x + m_Control->GetSize().x; + if (inLocation.x + ::dtol(theWidth) > theRightMargin) // re-centers this + inLocation.x = theRightMargin - ::dtol(theWidth) / 2; + + // Convert the point to screen coordinates + ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y); + ClientToScreen(&theScreenCoords); + m_Tooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true); + } + // If the tooltip text is empty, hide the tooltip + else + m_Tooltip.ShowWindow(SW_HIDE); + } +} + +//============================================================================= +/** + * Hides any tooltip currently being displayed. + */ +void CWndControl::HideTooltips() +{ + m_Tooltip.ShowWindow(SW_HIDE); +} + +//============================================================================= +/** + * Starts the Dragging process. + * On the given IDragable. + * @param inAsset the Asset to be drug. + */ +void CWndControl::DoStartDrag(IDragable *inDragable) +{ + // Tell the window that we are beginning a drag + if (inDragable && !m_IsDragging) { + // This should prevent the Container from dragging while it is already dragging. + SetIsDragging(true); + + // This is a Wrapper for the OLEDROP + CWinDragManager theDragManager; + + // Theoretically: there is no limit to the amount of data you can add. + // For now only one object will work, until i figure out how to drag multiple objects in + // windows. + Q3DStudio::CAutoMemPtr<CDropSource> theDropSource = + CDropSourceFactory::Create(inDragable->GetFlavor(), inDragable); + + // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls. + theDragManager.AddData(inDragable->GetFlavor(), &theDropSource, sizeof(CDropSource *)); + // This is a blocking call when we get done with this call we should have no more data in + // our Drag list. + theDragManager.StartDrag(); + + // Tell the window that we are done dragging + SetIsDragging(false); + } +} + +//=============================================================================== +/** +* performs a drag operation on a file +*/ +void CWndControl::DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList) +{ + // Tell the window that we are beginning a drag + if (!m_IsDragging) { + SetIsDragging(true); + + try { + CWinDragManager theDragManager; + + std::vector<Q3DStudio::CString>::iterator thePos = inDragFileNameList.begin(); + std::vector<Q3DStudio::CString>::iterator theEndPos = inDragFileNameList.end(); + + Q3DStudio::CAutoMemPtr<CDropSource> theDropSource; + Q3DStudio::CAutoMemPtr<CUICFile> theDragFile; + for (; thePos != theEndPos; ++thePos) { + Q3DStudio::CString theDragFileName = *thePos; + if (theDragFileName.Length() > 0) { + theDragFile = new CUICFile(theDragFileName); + theDropSource = CDropSourceFactory::Create( + EUIC_FLAVOR_ASSET_UICFILE, (void *)theDragFile, sizeof(theDragFile)); + // Add the UIC_GESTURE_FLAVOR. This will allow us to drag to StudioControls. + theDragManager.AddData(EUIC_FLAVOR_ASSET_UICFILE, &theDropSource, + sizeof(CDropSource *)); + break; + } + } + theDragManager.StartDrag(); + } catch (...) { // if there are any errors that throws an exception, there + // there will be no more drag and drop, since the flag will not be reset. + } + // Tell the window that we are done dragging + SetIsDragging(false); + } +} + +//============================================================================= +/** + * Notification of a mouse wheel movement. + */ +BOOL CWndControl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) +{ + ScreenToClient(&pt); + if (m_Control) + m_Control->OnMouseWheel(CPt(pt.x, pt.y), zDelta, CHotKeys::GetCurrentKeyModifiers()); + + //Q_UNUSED( nFlags ); + //Q_UNUSED( zDelta ); + //Q_UNUSED( pt ); + return CWnd::OnMouseWheel(nFlags, zDelta, pt); +} + +LRESULT CWndControl::OnRegisteredMouseWheel(WPARAM, LPARAM) +{ + return 0; +} + +//============================================================================= +/** + * Notification that this window is being resized. + */ +void CWndControl::OnSizing(UINT nSide, LPRECT lpRect) +{ + Q_UNUSED(nSide); + Q_UNUSED(lpRect); +} + +//============================================================================= +/** + * Override of erase to prevent flashing of the background. + */ +BOOL CWndControl::OnEraseBkgnd(CDC *pDC) +{ + Q_UNUSED(pDC); + return FALSE; +} + +//============================================================================= +/** + * Notification that this window has been resized. + */ +void CWndControl::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + MoveWindow(0, 0, cx, cy); + + CRect theSize; + GetClientRect(&theSize); + + if (m_Control) + m_Control->SetSize(CPt(theSize.right, theSize.bottom)); + + // Gotta recreate the buffered objects, otherwise they will be the wrong dimensions + DeleteBuffers(); +} + +//============================================================================= +/** + * Event notification that the mouse has moved. + */ +void CWndControl::OnMouseMove(UINT, CPoint point) +{ +#ifdef _DEBUG + m_IsPainting = true; +#endif + + UICPROFILE(OnMouseMove); + + // Track the mouse while it's in here, this will give us the hover msg + m_MouseOver = true; + + TRACKMOUSEEVENT theEventStruct; + theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT); + theEventStruct.dwFlags = TME_HOVER | TME_LEAVE; + theEventStruct.hwndTrack = GetSafeHwnd(); + theEventStruct.dwHoverTime = HOVER_DEFAULT; + + ::TrackMouseEvent(&theEventStruct); + + // Notify the control that the mouse moved + if (m_Control) { + m_Control->OnMouseMove(CPt(point.x, point.y), CHotKeys::GetCurrentKeyModifiers()); + + // If the control invalidated because of a mouse event then we want to do an immediate + // redraw. + // this ensures consistent visible feedback. + if (m_Control->IsChildInvalidated()) { + UICPROFILE(RedrawWindow); + RedrawWindow(nullptr, nullptr, RDW_UPDATENOW); + } + } + +#ifdef _DEBUG + m_IsPainting = false; +#endif +} + +//============================================================================= +/** + * Notification that the mouse has left this window. + */ +LRESULT CWndControl::OnMouseLeave(WPARAM inwParam, LPARAM inlParam) +{ +#ifdef _DEBUG + if (!m_IsPainting) { +#endif _DEBUG + + Q_UNUSED(inwParam); + Q_UNUSED(inlParam); + + CPoint thePoint; + + ::GetCursorPos(&thePoint); + + // This will tell me what window is under this point. + HWND theWindow = ::WindowFromPoint(thePoint); + + if (theWindow != m_hWnd) { + m_MouseOver = false; + if (m_Control) + m_Control->OnMouseMove(CPt(-1, -1), 0); + } + +#ifdef _DEBUG + } +#endif + + return 0; +} + +//============================================================================= +/** + * Override to provide the hover message to the control. + */ +LRESULT CWndControl::OnMouseHover(WPARAM inwParam, LPARAM inlParam) +{ + + long theX = inlParam & 0xFFFF; + long theY = (inlParam >> 16) & 0xFFFF; + + if (m_Control) + m_Control->OnMouseHover(CPt(theX, theY), (UINT)inwParam); + + TRACKMOUSEEVENT theEventStruct; + theEventStruct.cbSize = sizeof(TRACKMOUSEEVENT); + theEventStruct.dwFlags = TME_HOVER | TME_LEAVE; + theEventStruct.hwndTrack = GetSafeHwnd(); + theEventStruct.dwHoverTime = HOVER_DEFAULT; + + ::TrackMouseEvent(&theEventStruct); + + return 0; +} + +//============================================================================= +/** + * Callback from the control that it has been invalidated. + * This will post a message for a redraw. + */ +void CWndControl::OnControlInvalidated() +{ + if (::IsWindow(m_hWnd)) { + Invalidate(); + ::PostMessage(m_hWnd, WM_PAINT, 0, 0); + } +} + +//============================================================================= +/** + * Override of PreTranslateMessage for dragging implementation. + */ +BOOL CWndControl::PreTranslateMessage(MSG *inMessage) +{ + BOOL theReturn = FALSE; + + switch (inMessage->message) { + case WM_KEYDOWN: { + theReturn = + OnKeyDown((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam); + + BYTE theKeyboardState[256]; + ::GetKeyboardState(theKeyboardState); + + theKeyboardState[VK_CONTROL] = 0; + + WORD theChar = 0; + // Get the ascii character for the VK key. + ::ToAscii((UINT)inMessage->wParam, (inMessage->lParam >> 16) & 0xFF, theKeyboardState, + &theChar, 0); + unsigned int theCharacterCode = (char)theChar; + + if (theCharacterCode != 0) { + theReturn = theReturn + || OnChar(theCharacterCode, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam); + } + } break; + + case WM_KEYUP: + // Do the OnKeyUp + theReturn = + OnKeyUp((UINT)inMessage->wParam, inMessage->lParam & 0xFFFF, (UINT)inMessage->lParam); + break; + + case WM_CHAR: + theReturn = OnChar((UINT)inMessage->wParam, 0, 0); + break; + + default: + break; + } + + return theReturn; +} + +//============================================================================= +/** + * Call this function to indicate that a drag operation is currently taking + * place or has just finished. If the drag operation just finished, a mouse up + * event will be sent to all children so that the one who initiated the drag + * can clean things up. + * @param inIsDragging true to specify that a drag is occurring or false if a drag ended + */ +void CWndControl::SetIsDragging(bool inIsDragging) +{ + m_IsDragging = inIsDragging; + + // If we are no longer dragging, notify the children that a mouse up occurred since OLE won't + // tell us that + if (!m_IsDragging) + m_Control->OnMouseUp(CPt(-1, -1), 0); +} + +//============================================================================= +/** + * Override of MouseActivate to set the focus on this. + */ +int CWndControl::OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message) +{ + CWnd::OnMouseActivate(pDesktopWnd, nHitTest, message); + SetFocus(); + m_Control->OnGainFocus(); + return MA_ACTIVATE; +} + +bool CWndControl::OnDragWithin(CDropSource &inSource) +{ + bool theReturn = false; + CPt thePoint = inSource.GetCurrentPoint(); + long theFlags = inSource.GetCurrentFlags(); + CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags); + + if (theDropTarget) { + theReturn = theDropTarget->Accept(inSource); + delete theDropTarget; + } + return theReturn; +} + +bool CWndControl::OnDragReceive(CDropSource &inSource) +{ + bool theReturn = false; + CPt thePoint = inSource.GetCurrentPoint(); + long theFlags = inSource.GetCurrentFlags(); + + CDropTarget *theDropTarget = m_Control->FindDropCandidate(thePoint, theFlags); + + if (theDropTarget) { + theReturn = theDropTarget->Drop(inSource); + delete theDropTarget; + } + return theReturn; +} + +void CWndControl::OnDragLeave() +{ + m_MouseOver = false; + m_Control->OnMouseMove(CPt(-1, -1), 0); +} + +void CWndControl::OnReflectMouse(CPt &inPoint, long inFlags) +{ + // Notify the control that the mouse moved + m_Control->OnMouseMove(inPoint, inFlags /*CHotKeys::GetCurrentKeyModifiers( )*/); + + // If the control invalidated because of a mouse event then we want to do an immediate redraw. + // this ensures consistent visible feedback. + if (m_Control->IsChildInvalidated()) { + UICPROFILE(RedrawWindow); + RedrawWindow(nullptr, nullptr, RDW_UPDATENOW); + } +} + +void CWndControl::ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct) +{ + // If the global preference for tooltips is enabled + if (CStudioPreferences::ShouldShowTooltips()) { + // This flag is set when the control is created, it tells itself that things should + // not move around outside its boundaries. + if (inLocation.x < inBoundingRct.position.x) + inLocation.x = inBoundingRct.position.x; + if (inLocation.y < inBoundingRct.position.y) + inLocation.y = inBoundingRct.position.y; + if (inLocation.x > (inBoundingRct.position.x + inBoundingRct.size.x)) + inLocation.x = inBoundingRct.position.x + inBoundingRct.size.x; + if (inLocation.y > (inBoundingRct.position.y + inBoundingRct.size.y)) + inLocation.y = inBoundingRct.position.y + inBoundingRct.size.y; + + // Convert the point to screen coordinates + ::CPoint theScreenCoords = ::CPoint(inLocation.x, inLocation.y); + ClientToScreen(&theScreenCoords); + // If the tooltip text is not empty, show the tooltip + if (!inText.IsEmpty()) + m_MoveableTooltip.UpdateToolTip(theScreenCoords, ::CString(inText.GetMulti()), true); + // If the tooltip text is empty, hide the tooltip + else + m_MoveableTooltip.ShowWindow(SW_HIDE); + } +} + +void CWndControl::HideMoveableWindow() +{ + m_MoveableTooltip.ShowWindow(SW_HIDE); +} + +//============================================================================= +/** + * Override of OnCtlColor( ) to provide a callback when the dialog is closed. + */ +HBRUSH CWndControl::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor) +{ + // Call the base class implementation first! Otherwise, it may undo what we are trying to + // accomplish here. + HBRUSH hbr = CWnd::OnCtlColor(pDC, pWnd, nCtlColor); + + // Set the text color to red. + // pDC->SetTextColor(RGB(255, 0, 0)); + + // pDC->SetBkColor( CStudioPreferences::GetBaseColor( ) ); + + // Return handle to our CBrush object. + // hbr = m_Brush; + + return hbr; +} + +//============================================================================= +/** + * Override of EN_CHANGE + */ +void CWndControl::OnEnChange() +{ +} diff --git a/src/Authoring/Studio/_Win/Controls/WndControl.h b/src/Authoring/Studio/_Win/Controls/WndControl.h new file mode 100644 index 00000000..a7e3c72a --- /dev/null +++ b/src/Authoring/Studio/_Win/Controls/WndControl.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_WND_CONTROL_H +#define INCLUDED_WND_CONTROL_H 1 + +#pragma once + +#include "Control.h" +#include "PopupWnd.h" +#include "DropContainer.h" + +#define WNDCONTROL_CLASSNAME _T("WNDCONTROL") + +class CWndControl; +class IDragable; + +class CWndControlControlListener : public CControlWindowListener +{ +public: + CWndControlControlListener(CWndControl *inParent); + virtual void OnControlInvalidated(); + virtual long DoPopup(CContextMenu *inMenu, CPt inLocation); + virtual CPt ClientToScreen(CPt inPoint); + virtual CPt ScreenToClient(CPt inPoint); + virtual TPlatformView GetPlatformView(); + virtual void SetIsDragging(bool inIsDragging); + virtual void ShowTooltips(CPt inLocation, Q3DStudio::CString inText); + virtual void HideTooltips(); + virtual void DoStartDrag(IDragable *inDragable); + virtual void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList); + virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct); + virtual void HideMoveableWindow(); + +protected: + CWndControl *m_Parent; +}; + +class CWndControl : public CWnd, public CWinDropContainer +{ + +public: + CWndControl(CControl *inAgent); + virtual ~CWndControl(); + + DEFINE_OBJECT_COUNTER(CWndControl) + + BOOL RegisterWindowClass(); + + virtual void OnControlInvalidated(); + long DoPopup(CContextMenu *inMenu, CPt inLocation); + void SetIsDragging(bool inIsDragging); + void DeleteBuffers(); + bool OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags); + bool OnKeyUp(UINT inChar, UINT inRepCnt, UINT inFlags); + bool OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + void ShowTooltips(CPt inLocation, Q3DStudio::CString inText); + void HideTooltips(); + void DoStartDrag(IDragable *inDragable); + void DoStartDrag(std::vector<Q3DStudio::CString> &inDragFileNameList); + virtual void ShowMoveableWindow(CPt inLocation, Q3DStudio::CString inText, CRct inBoundingRct); + virtual void HideMoveableWindow(); + + bool OnDragWithin(CDropSource &inSource); + bool OnDragReceive(CDropSource &inSource); + void OnDragLeave(); + void OnReflectMouse(CPt &inPoint, long inFlags); + + //{{AFX_MSG(CWndControl) + afx_msg void OnKillFocus(CWnd *pNewWnd); + afx_msg void OnSetFocus(CWnd *pOldWnd); + afx_msg void OnPaint(); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonUp(UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnSizing(UINT nFlags, LPRECT pRect); + afx_msg BOOL OnEraseBkgnd(CDC *pDC); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg LRESULT OnRegisteredMouseWheel(WPARAM wParam, LPARAM lParam); + afx_msg int OnMouseActivate(CWnd *pDesktopWnd, UINT nHitTest, UINT message); + afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor); + afx_msg void OnEnChange(); + //}}AFX_MSG + + afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam); + afx_msg LRESULT OnMouseHover(WPARAM inwParam, LPARAM inlParam); + DECLARE_MESSAGE_MAP() +protected: + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLibraryView) +public: +protected: + virtual BOOL PreTranslateMessage(MSG *pMsg); + //}}AFX_VIRTUAL + + CControl *m_Control; + CControl *m_Focus; + CPopupWnd m_Tooltip; + CPopupWnd m_MoveableTooltip; + CBrush m_Brush; + bool m_MouseOver; + CDC *m_MemDC; + HBITMAP m_MemBitmap; + HBITMAP m_OldBitmap; + bool m_IsMouseDown; /// This is used for a hack to make controls get a mouse up when we lose + /// focuse and +/// the mouse is down... say we try and delete a layer while dragging and it is the last layer + +#ifdef _DEBUG + bool m_IsPainting; +#endif + bool m_IsDragging; + CWndControlControlListener m_ControlListener; +}; + +#endif // INCLUDED_WND_CONTROL_H diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp new file mode 100644 index 00000000..ac835c00 --- /dev/null +++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.cpp @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "HotKeys.h" +#include "DropProxy.h" +#include "DropContainer.h" +#include "DropSource.h" +#include "UICFile.h" +#include "UICString.h" +#include "IDragable.h" + +#include <QDragEnterEvent> +#include <QWidget> + +//============================================================================= +/** + * Constructor + * @param inParent gesture listener that messages will be passed to + */ +CDropProxy::CDropProxy(CDropContainer *inParent) +{ + m_Parent = inParent; +} + +//============================================================================= +/** + * Destructor + */ +CDropProxy::~CDropProxy() +{ +} + +//============================================================================= +/** + * Called when a drag begins over a window. + */ +void CDropProxy::dragEnterEvent(QDragEnterEvent *event) +{ + event->ignore(); + if (GetDragItemCount(event->mimeData())) { + CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin(); + CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd(); + + for (; theItr != theEnd; ++theItr) { + if (HasMainFlavor(event->mimeData(), *theItr)) { + event->accept(); + event->setDropAction(Qt::CopyAction); + break; + } + } + } +} + +//=============================================================================== +/** + * This will extract the Data from the OLEDropObject and convert it to a CDropSource. + * @param inDataObject the Win specific dropSource. + * @param inFlavor the Flavor we need. + * @param inItem the position of the data in the DataObject. + * @return Newly extracted or created DropSource. + * Note: if we created it we need to make sure we destroy this object. + */ +CDropSource *CDropProxy::GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem) +{ + const CDropSource *theDropSource = nullptr; + switch (inFlavor) { + case EUIC_FLAVOR_FILE: { + // Check if we have a Drop File on our hands. + if (inDataObject->hasUrls()) { + // Get the number of files being dragged + short theFileCount = inDataObject->urls().count(); + + // Only allow single files to be dragged + if (theFileCount > inItem && !inDataObject->urls().isEmpty()) { + // Get the filename of the object being dragged + QString theFilename = inDataObject->urls().at(inItem).toLocalFile(); + + CUICFile theFile(Q3DStudio::CString::fromQString(theFilename)); + // Dragging a single file + theDropSource = + CDropSourceFactory::Create(EUIC_FLAVOR_FILE, &theFile, sizeof(CUICFile *)); + } + } + } break; + case EUIC_FLAVOR_TEXT: + // Don't do anythiing for this + case EUIC_FLAVOR_LISTBOX: + // Don't do anythiing for this + case EUIC_FLAVOR_BASIC_OBJECTS: + // Don't do anythiing for this + case EUIC_FLAVOR_ASSET_LIB: + // make an Aset out of this. + case EUIC_FLAVOR_ASSET_TL: + // make an Aset out of this. + case EUIC_FLAVOR_ASSET_UICFILE: + // make an Aset out of this. + // Get a pointer to the object + theDropSource = dynamic_cast<const CDropSource *>(inDataObject); + if (theDropSource != nullptr && theDropSource->GetFlavor() != inFlavor) + theDropSource = nullptr; + break; + } + return const_cast<CDropSource *>(theDropSource); +} + +//=============================================================================== +/** + * This is to count the number of objects in the DataObject. + * @param inDataObject the WinSpecific dropobject + * @return The number of items found. + */ +long CDropProxy::GetDragItemCount(const QMimeData *inDataObject) +{ + long theCount = 0; + + // Check if we have a Drop File on our hands. + if (inDataObject->hasUrls()) { + // Get the number of files being dragged + theCount = inDataObject->urls().count(); + } else { + auto source = dynamic_cast<const CDropSource *>(inDataObject); + theCount = source != nullptr ? 1 : 0; + } + + return theCount; +} +//=============================================================================== +/** + * This will check the DataObject for the Flavor. + * @param inDataObject the Win specific data object. + * @param inFlavor the requested Flavor. + * @param true if the DataObject contains the flavor. + */ +bool CDropProxy::HasMainFlavor(const QMimeData *inDataObject, long inFlavor) +{ + if (inFlavor == EUIC_FLAVOR_FILE) + return inDataObject->hasUrls(); + auto source = dynamic_cast<const CDropSource *>(inDataObject); + return source != nullptr && source->GetFlavor() == inFlavor; +} + +//============================================================================= +/** + * Called when a drag event leaves the window. May cause the drag to end if + * the mouse button is no longer down. + */ +void CDropProxy::dragLeaveEvent(QDragLeaveEvent *event) +{ + if (m_Parent) { + m_Parent->OnDragLeave(); + event->accept(); + } +} + +//============================================================================= +/** + * Called when an item is being dragged over this window. Passes the message + * on to the gesture listener. + */ +void CDropProxy::dragMoveEvent(QDragMoveEvent *event) +{ + bool theAcceptFlag = false; + + if (m_Parent) { + long theCount = GetDragItemCount(event->mimeData()); + for (long theIndex = 0; theIndex < theCount; ++theIndex) { + Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y()); + + CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin(); + CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd(); + + for (; theItr != theEnd; ++theItr) { + // Find the Flavor of this Item. + if (HasMainFlavor(event->mimeData(), *theItr)) { + CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex); + if (theDropSource) { + CPt thePoint(event->pos()); + theModifyerFlags = CHotKeys::GetCurrentKeyModifiers(); + theDropSource->SetCurrentPoint(thePoint); + theDropSource->SetCurrentFlags(theModifyerFlags); + + theDropSource->InterpretKeyFlags(theModifyerFlags); + // This will be implemented in the cross platform code. + theAcceptFlag = m_Parent->OnDragWithin(*theDropSource); + event->setAccepted(theAcceptFlag); + if (theAcceptFlag) { + if (theDropSource->CanCopy()) + event->setDropAction(Qt::CopyAction); + else + event->setDropAction(Qt::MoveAction); + // Breakout of the outer loop. + theIndex = theCount; + } + + // delete the drop source if it was a file + if (EUIC_FLAVOR_FILE == theDropSource->GetFlavor()) { + delete theDropSource; + } + break; + } + } + } + } + } +} + +//============================================================================= +/** + * Called when an OLE item is dropped on this window. + * @return TRUE if the drop was valid, otherwise FALSE + */ +void CDropProxy::dropEvent(QDropEvent *event) +{ + if (m_Parent) { + long theCount = GetDragItemCount(event->mimeData()); + for (long theIndex = 0; theIndex < theCount; ++theIndex) { + Qt::KeyboardModifiers theModifyerFlags = ReflectMouse(event->pos().x(), event->pos().y()); + + theModifyerFlags = CHotKeys::GetCurrentKeyModifiers(); + + CDropContainer::TFlavorItr theItr = m_Parent->GetFlavorBegin(); + CDropContainer::TFlavorItr theEnd = m_Parent->GetFlavorEnd(); + + for (; theItr != theEnd; ++theItr) { + // Find the Flavor of this Item. + if (HasMainFlavor(event->mimeData(), *theItr)) { + // This will convert all stuff into a DropSource + CDropSource *theDropSource = GetDropSource(event->mimeData(), *theItr, theIndex); + + // This will be implemented in the cross platform code. + if (theDropSource) { + CPt thePoint(event->pos()); + theDropSource->SetCurrentPoint(thePoint); + theDropSource->SetCurrentFlags(theModifyerFlags); + + // Don't call the recieve if we did not have a valid droptarget to begin + // with. + if (theDropSource->GetHasValidTarget()) { + theDropSource->InterpretKeyFlags(theModifyerFlags); + // This will be implemented in the cross platform code. + m_Parent->OnDragReceive(*theDropSource); + } + } + + // Don't delete the drop source here, the creator will destroy it + // delete theDropSource; + } + } + } + } + + event->accept(); +} +//=============================================================================== +/** + * This function is used to report back to the container where the mouse is during a drag. + * The container can send this to children as MouseOvers so the children can do mouseover + *things. + * @param inX the X position + * @param inY the Y position. + * @return the Key modifyers. + */ +Qt::KeyboardModifiers CDropProxy::ReflectMouse(long inX, long inY) +{ + Qt::KeyboardModifiers theModifierFlags = Qt::NoModifier; + + if (m_Parent) { + // Get the mouse stuff + CPt theMouseLoc(inX, inY); + + // Determine which modifier keys are down so that we can pass them along + + theModifierFlags = CHotKeys::GetCurrentKeyModifiers(); + + // Pass the gesture into the studio control + m_Parent->OnReflectMouse(theMouseLoc, theModifierFlags); + } + return theModifierFlags; +} + +void CDropProxy::Register(QWidget *widget) +{ + widget->installEventFilter(this); + widget->setAcceptDrops(true); +} + +bool CDropProxy::eventFilter(QObject *watched, QEvent *event) +{ + Q_UNUSED(watched); + + switch (event->type()) { + case QEvent::DragEnter: + dragEnterEvent(static_cast<QDragEnterEvent *>(event)); + return event->isAccepted(); + case QEvent::DragLeave: + dragLeaveEvent(static_cast<QDragLeaveEvent *>(event)); + return event->isAccepted(); + case QEvent::DragMove: + dragMoveEvent(static_cast<QDragMoveEvent *>(event)); + return event->isAccepted(); + case QEvent::Drop: + dropEvent(static_cast<QDropEvent *>(event)); + return event->isAccepted(); + default: + return false; + } +} diff --git a/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h new file mode 100644 index 00000000..eadb9b83 --- /dev/null +++ b/src/Authoring/Studio/_Win/DragNDrop/DropProxy.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_DROP_PROXY +#define INCLUDED_DROP_PROXY 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include <QObject> + +//============================================================================== +// Forwards +//============================================================================== + +class CDropContainer; +class CStudioApp; +class CDropSource; + +class QDragEnterEvent; +class QDragLeaveEvent; +class QDragMoveEvent; +class QDropEvent; +class QMimeData; + +class CDropProxy : public QObject +{ + Q_OBJECT +public: + CDropProxy(CDropContainer *inParent); + virtual ~CDropProxy(); + + void dragEnterEvent(QDragEnterEvent *event); + void dragLeaveEvent(QDragLeaveEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + + CDropSource *GetDropSource(const QMimeData *inDataObject, long inFlavor, long inItem); + long GetDragItemCount(const QMimeData *inDataObject); + bool HasMainFlavor(const QMimeData *inDataObject, long inFlavor); + Qt::KeyboardModifiers ReflectMouse(long inX, long inY); + + void Register(QWidget* widget); + + bool eventFilter(QObject *watched, QEvent *event) override; + +protected: + CDropContainer *m_Parent; +}; + +#endif // INCLUDED_DROP_PROXY diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp new file mode 100644 index 00000000..d6216200 --- /dev/null +++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 1999-2003 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "stdafx.h" +#include "WinDnd.h" +#include "DropSource.h" + +//=============================================================================== +/** + * Constructor + */ +CWinDragManager::CWinDragManager() +{ + memset(&m_DragItem, 0, sizeof(SDropItem)); +} + +//=============================================================================== +/** + * Dtor + */ +CWinDragManager::~CWinDragManager() +{ +} + +//=============================================================================== +/** + * This will take any data flavor and wrap it up into out drag data. + */ +void CWinDragManager::AddData(long inFlavor, void *inData, unsigned long inSize) +{ + m_DragItem.m_Flavor = inFlavor; + m_DragItem.m_Data = inData; + m_DragItem.m_Size = inSize; +} + +//=============================================================================== +/** + * I made this so it would kind of match the MAC version. + */ +void CWinDragManager::StartDrag() +{ + Track(); +} + +//=============================================================================== +/** + * This is the Blocking function that does the Dragging. + * It is assumed that all of the Data is is requested to be dragged, is already in the list + * and we take it out of the list and pack it into the Win OLEDropSource and let it go. + * We should only return when the whole operation is over. + */ +void CWinDragManager::Track() +{ + // Convert our data into a OLE DragSource. + HGLOBAL theGlobalData = nullptr; + COleDataSource theDataSource; + + // Empty the data source + theDataSource.Empty(); + + // long theDataSize = m_DragItem.m_Size; + void *theData = m_DragItem.m_Data; + long theFlavor = m_DragItem.m_Flavor; + + // if ( theDataSize > 0 ) + { + // Allocate a global block of data + DWORD theGlobalObjectSize = sizeof(CDropSource *);//sizeof(long /*theDataSize*/); + theGlobalData = GlobalAlloc(GHND, theGlobalObjectSize); + + // Lock down the global memory object for copying data + CDropSource *theDropSource = reinterpret_cast<CDropSource *>(GlobalLock(theGlobalData)); + + // Copy the CDropSource pointer + CopyMemory(theDropSource, theData, theGlobalObjectSize); + + // Unlock, but do not free + GlobalUnlock(theGlobalData); + + // Prepare OLE data for transfer + theDataSource.CacheGlobalData((CLIPFORMAT)theFlavor, theGlobalData, nullptr); + } + + // This will go through the framework. + if (DROPEFFECT_NONE == theDataSource.DoDragDrop()) { + theDataSource.Empty(); + if (theGlobalData) + ::GlobalFree(theGlobalData); + } +} diff --git a/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h new file mode 100644 index 00000000..8af759c7 --- /dev/null +++ b/src/Authoring/Studio/_Win/DragNDrop/WinDnd.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 1999-2003 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#ifndef INCLUDED_WINDND +#define INCLUDED_WINDND + +#include <map> + +typedef struct _SDropItem +{ + long m_Flavor; // The Type of Data. + void *m_Data; ///< A nullptr value will cause the Data to be created Later on ( Promise ) + unsigned long m_Size; //< The size of the Data. +} SDropItem; + +//============================================================================= +/** + * This class only supports dragging one item. + */ +class CWinDragManager +{ +protected: + SDropItem m_DragItem; ///< the dragged item + +public: + CWinDragManager(); + virtual ~CWinDragManager(); + + void Track(); + void StartDrag(); + + void AddData(long inFlavor, void *inData, unsigned long inSize); +}; + +#endif diff --git a/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h new file mode 100644 index 00000000..114e3bf8 --- /dev/null +++ b/src/Authoring/Studio/_Win/Include/StudioPrefixWin32.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_STUDIO_PREFIX_WIN_32_H +#define INCLUDED_STUDIO_PREFIX_WIN_32_H 1 + +#pragma once + +#define AK_LITTLE_ENDIAN +//#define WIN32 + +#include <float.h> + +#endif // INCLUDED_STUDIO_PREFIX_WIN_32_H diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp new file mode 100644 index 00000000..41f0fe42 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.cpp @@ -0,0 +1,902 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== +#include "PaletteManager.h" +#include "StudioApp.h" +#include "Views.h" +#include "MainFrm.h" +#include "StringLoader.h" +#include "TimelineControl.h" +#include "BasicObjectsView.h" +#include "SlideView.h" +#include "StringTokenizer.h" +#include "Preferences.h" +#include "WidgetControl.h" +#include "InspectorControlView.h" +#include "ActionView.h" +#include "IDragable.h" +#include "ActionView.h" +#include "ProjectView.h" +#include "TabOrderHandler.h" + +#include <QDockWidget> + +//============================================================================== +/** + * Class for std::for_each to delete each control + */ +template <class T> +class CDeleteAll +{ +public: + void operator()(const T *inControl) const { delete inControl; } +}; + +//============================================================================== +/** + * Constructor + */ +CPaletteManager::CPaletteManager(CMainFrame *inMainFrame) + : m_MainFrame(inMainFrame) +{ + // Position tabs to the right + inMainFrame->setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::East); + + QDockWidget *basicObjectsDock = new QDockWidget(QObject::tr("Basic Objects"), inMainFrame); + basicObjectsDock->setObjectName("basic_objects"); + basicObjectsDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea + | Qt::BottomDockWidgetArea); + auto basicObjectsView = new BasicObjectsView(basicObjectsDock); + basicObjectsDock->setWidget(basicObjectsView); + inMainFrame->addDockWidget(Qt::RightDockWidgetArea, basicObjectsDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_BASICOBJECTS, basicObjectsDock)); + + QDockWidget *projectDock = new QDockWidget(QObject::tr("Project"), inMainFrame); + projectDock->setObjectName("project"); + projectDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea + | Qt::BottomDockWidgetArea); + auto projectView = new ProjectView(projectDock); + projectDock->setWidget(projectView); + inMainFrame->addDockWidget(Qt::RightDockWidgetArea, projectDock); + inMainFrame->tabifyDockWidget(basicObjectsDock, projectDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_PROJECT, projectDock)); + + QDockWidget *slideDock = new QDockWidget(QObject::tr("Slide"), inMainFrame); + slideDock->setObjectName("slide"); + slideDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + auto slideView = new SlideView(slideDock); + slideDock->setWidget(slideView); + inMainFrame->addDockWidget(Qt::LeftDockWidgetArea, slideDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_SLIDE, slideDock)); + + QDockWidget *timelineDock = new QDockWidget(QObject::tr("Timeline"), inMainFrame); + timelineDock->setObjectName("timeline"); + timelineDock->setAllowedAreas(Qt::BottomDockWidgetArea); + auto c = new CTimelineControl(); + auto w = new WidgetControl(c, timelineDock); + timelineDock->setWidget(w); + w->setMinimumWidth(500); + inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, timelineDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_TIMELINE, timelineDock)); + + int actionViewMinWidth = CStudioPreferences::valueWidth() + + CStudioPreferences::idWidth() + 40; // 40 added to accommodate tabs + + QDockWidget *actionDock = new QDockWidget(QObject::tr("Action"), inMainFrame); + actionDock->setObjectName("action"); + actionDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea + | Qt::BottomDockWidgetArea); + auto actionView = new ActionView(actionDock); + actionDock->setWidget(actionView); + actionView->setMinimumWidth(actionViewMinWidth); + inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, actionDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_ACTION, actionDock)); + + QDockWidget *inspectorDock = new QDockWidget(QObject::tr("Inspector Control"), inMainFrame); + inspectorDock->setObjectName("inspector_control"); + inspectorDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea + | Qt::BottomDockWidgetArea); + auto inspectorView = new InspectorControlView(inspectorDock); + inspectorDock->setWidget(inspectorView); + inspectorView->setMinimumWidth(actionViewMinWidth); // Same min size as action view + inMainFrame->addDockWidget(Qt::BottomDockWidgetArea, inspectorDock); + inMainFrame->tabifyDockWidget(actionDock, inspectorDock); + m_ControlList.insert(std::make_pair(CONTROLTYPE_INSPECTOR, inspectorDock)); + + w->RegiserForDnd(w); + w->AddMainFlavor(EUIC_FLAVOR_LISTBOX); + w->AddMainFlavor(EUIC_FLAVOR_FILE); + w->AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE); + w->AddMainFlavor(EUIC_FLAVOR_ASSET_LIB); + w->AddMainFlavor(EUIC_FLAVOR_ASSET_TL); + w->AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS); + + // Set to a default state + Reset(); +} + +//============================================================================== +/** + * Destructor + */ +CPaletteManager::~CPaletteManager() +{ + TControlMap::iterator theIterator = m_ControlList.begin(); + TControlMap::iterator theEndIterator = m_ControlList.end(); +#ifdef KDAB_TEMPORARILY_REMOVED + for (; theIterator != theEndIterator; ++theIterator) { + // Remove the palette from the old master + long theType = theIterator->first; + CMasterControl *theOldMaster = FindMasterPalette(theType); + if (theOldMaster) + RemoveControlFromMaster(theOldMaster, theType); + } + std::for_each(m_PaletteList.begin(), m_PaletteList.end(), CDeleteAll<CStudioPaletteBar>()); +#endif + // Delete all the controls + for (theIterator = m_ControlList.begin(); theIterator != theEndIterator; ++theIterator) + delete theIterator->second; +} + +//============================================================================== +/** + * Clear out old lists and reset all the palettes + */ +void CPaletteManager::Reset() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Set the visible state to false + TControlMap::iterator theIterator = m_ControlList.begin(); + TControlMap::iterator theEndIterator = m_ControlList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + CControl *theControl = theIterator->second; + if (theControl) + theControl->SetVisible(false); + } + + // Undock all palette + TPaletteList::iterator thePaletteIterator = m_PaletteList.begin(); + for (; thePaletteIterator != m_PaletteList.end(); ++thePaletteIterator) { + CStudioPaletteBar *thePaletteBar = (*thePaletteIterator); + thePaletteBar->ShowPalette(false); + } +#endif +} + +//============================================================================== +/** + * Create a palette + */ +CStudioPaletteBar *CPaletteManager::CreatePalette() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Build the create context + CCreateContext theCreateContext; + memset(&theCreateContext, 0, sizeof(CCreateContext)); + theCreateContext.m_pNewViewClass = RUNTIME_CLASS(CMasterView); + theCreateContext.m_pCurrentFrame = m_MainFrame; + + // Create the palette bar + CStudioPaletteBar *thePaletteBar = new CStudioPaletteBar; + thePaletteBar->Create(::CString("<empty>"), &theCreateContext, GetUniquePaletteId(), + m_MainFrame); + + // Set the provider + CMasterView *theMasterView = (CMasterView *)thePaletteBar->GetView(); + theMasterView->SetProvider(this); + + // Must occur after the provider is set + thePaletteBar->InitialUpdate(); + + // Save the palette + ASSERT(thePaletteBar != nullptr); + m_PaletteList.push_back(thePaletteBar); + + // Store the information + TSMasterInfo theInfo; + theInfo.m_Master = theMasterView->GetMasterControl(); + theInfo.m_PaletteBar = thePaletteBar; + + ASSERT(theInfo.m_PaletteBar != nullptr); + m_MasterList.push_back(theInfo); + + return thePaletteBar; +#endif + return nullptr; +} + +//============================================================================== +/** + * Find a master control with no contained controls + */ +CMasterControl *CPaletteManager::FindUnusedMaster() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + if (theIterator->m_Palettes.any() == false) + return theIterator->m_Master; + } +#endif + + return nullptr; +} + +CMasterControl *CPaletteManager::FindMasterByPaletteId(long inPaletteId) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + CControlBarInfo theBarInfo; + theIterator->m_PaletteBar->GetBarInfo(&theBarInfo); + + if (theBarInfo.m_nBarID == (UINT)inPaletteId) + return theIterator->m_Master; + } +#endif + return nullptr; +} + +CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(long inType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + if (theIterator->m_Palettes[inType] == true) + return theIterator->m_PaletteBar; + } +#endif + return nullptr; +} + +CStudioPaletteBar *CPaletteManager::FindStudioPaletteBar(CMasterControl *inMaster) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + if (theIterator->m_Master == inMaster) + return theIterator->m_PaletteBar; + } +#endif + return nullptr; +} + +//============================================================================== +/** + * Add a new master to the list of masters + */ +CMasterControl *CPaletteManager::AddMasterPalette(long inType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Remove the palette from the old master + CMasterControl *theOldMaster = FindMasterPalette(inType); + if (theOldMaster) + RemoveControlFromMaster(theOldMaster, inType); + + // Create a new master + CMasterControl *theMasterControl = FindUnusedMaster(); + if (theMasterControl != nullptr) { + // Add the palette to the new master + AddControlToMaster(theMasterControl, inType); + } + + return theMasterControl; +#endif + return nullptr; +} + +//============================================================================== +/** + * Add the specified palette to the specified master + */ +void CPaletteManager::AddControlToMaster(CMasterControl *inMaster, long inType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Make sure this is a valid type ( for backward compatibility ) + TControlMap::iterator theControlIterator = m_ControlList.find(inType); + if (theControlIterator != m_ControlList.end()) { + // Make sure the palette is not already on another master + CMasterControl *theOldMaster = FindMasterPalette(inType); + if (theOldMaster) + RemoveControlFromMaster(theOldMaster, inType); + + // Add the palette to this master + TMasterList::iterator theIterator = m_MasterList.begin(); + for (; theIterator != m_MasterList.end(); ++theIterator) { + if (theIterator->m_Master == inMaster) { + theIterator->m_Palettes[inType] = true; + theIterator->m_Master->AddControl(GetControlName(inType), inType, + theControlIterator->second); + theIterator->m_Master->Invalidate(); + break; + } + } + } +#endif +} + +//============================================================================== +/** + * Remove the specified palette from the specified master + */ +void CPaletteManager::RemoveControlFromMaster(CMasterControl *inMaster, long inType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + for (; theIterator != m_MasterList.end(); ++theIterator) { + if (theIterator->m_Master == inMaster) { + theIterator->m_Palettes[inType] = false; + theIterator->m_Master->RemoveControl(GetControl(inType)); + theIterator->m_Master->Invalidate(); + } + } +#endif +} + +//============================================================================== +/** + * Find the name of the master that contains this palette + */ +CMasterControl *CPaletteManager::FindMasterPalette(long inType) +{ + CMasterControl *theMaster = nullptr; + +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (; theIterator != theEndIterator; ++theIterator) { + if (theIterator->m_Palettes[inType] == true) { + theMaster = theIterator->m_Master; + break; + } + } +#endif + return theMaster; +} + +//============================================================================== +/** + * Query the number of masters + */ +long CPaletteManager::GetMasterCount() +{ + return (long)m_MasterList.size(); +} + +//============================================================================== +/** + * Get the master at the specified index + */ +CMasterControl *CPaletteManager::GetMaster(long inIndex) +{ + CMasterControl *theControl = nullptr; +#ifdef KDAB_TEMPORARILY_REMOVED + TMasterList::iterator theIterator = m_MasterList.begin(); + std::advance(theIterator, inIndex); + if (theIterator != m_MasterList.end()) + theControl = theIterator->m_Master; +#endif + return theControl; +} + +//============================================================================= +/** + * Force a control to become invisible + */ +void CPaletteManager::HideControl(long inType) +{ + auto dock = GetControl(inType); + + if (dock) { + // Make sure the control is invisible + dock->setVisible(false); + } +} +//============================================================================= +/** + * Detemine if a control is currently visible + */ +bool CPaletteManager::IsControlVisible(long inType) const +{ + auto dock = GetControl(inType); + return dock && dock->isVisible(); +} + +//============================================================================= +/** + * Force a control to become visible + */ +void CPaletteManager::ShowControl(long inType) +{ + auto dock = GetControl(inType); + + if (dock) { + // Make sure the control is visible + dock->setVisible(true); + dock->setFocus(); + } +} + +//============================================================================= +/** + * Flip the visible state of a control + */ +void CPaletteManager::ToggleControl(long inType) +{ + if (IsControlVisible(inType)) + HideControl(inType); + else + ShowControl(inType); +} + +//============================================================================== +/** + * Return the Control (Palette) according to its EControlTypes enum. + * @param inType EControlTypes + */ +QDockWidget *CPaletteManager::GetControl(long inType) const +{ + auto dock = m_ControlList.find(inType); + if (dock != m_ControlList.end() && dock->second) + return dock->second; + else + return nullptr; +} + +QWidget *CPaletteManager::getFocusWidget() const +{ + TControlMap::const_iterator end = m_ControlList.end(); + for (TControlMap::const_iterator iter = m_ControlList.begin(); iter != end; ++iter) { + if (iter->second->widget()->hasFocus()) + return iter->second->widget(); + } + return nullptr; +} + +bool CPaletteManager::tabNavigateFocusedWidget(bool tabForward) +{ + QWidget *palette = getFocusWidget(); + if (palette) { + if (auto inspector = qobject_cast<InspectorControlView *>(palette)) { + inspector->tabOrderHandler()->tabNavigate(tabForward); + return true; + } else if (auto actionview = qobject_cast<ActionView *>(palette)) { + actionview->tabOrderHandler()->tabNavigate(tabForward); + return true; + } + } + return false; +} + +//============================================================================== +/** + * A helper for CMainFrame::GetTimelineControl() to access the CTimelineControl + * inside the QDockWidget + */ +CTimelineControl *CPaletteManager::GetTimelineControl() const +{ + auto dock = GetControl(CPaletteManager::CONTROLTYPE_TIMELINE); + + if (dock) { + auto widget = static_cast<WidgetControl *>(dock->widget()); + + if (widget) + return static_cast<CTimelineControl *>(widget->getControl()); + } + + return nullptr; +} + +//============================================================================== +// Serialization +//============================================================================== + +//============================================================================== +/** + * Load the palette state from the registry + */ +bool CPaletteManager::Load() +{ + // Clear out existing local stuff + Reset(); + +#ifdef KDAB_TEMPORARILY_REMOVED + // Test the palette prefs, return false if they don't exist + if (CPreferences::GetUserPreferences().Exists(PALETTE_KEY) == false) + return false; + + long theCurrentPalette = 0; + while (true) { + // Format the subkey name + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%ls%ld", PALETTE_SUBKEY, theCurrentPalette); + + // Check to see if we should exit the for loop + CPreferences thePalettePrefs = CPreferences::GetUserPreferences(PALETTE_KEY); + if (thePalettePrefs.Exists(theSubKeyName) == false) + break; + + // Format the subkey name + Q3DStudio::CString theFullKeyName; + theFullKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theCurrentPalette); + + // Grab the prefs + CPreferences thePrefs = CPreferences::GetUserPreferences(theFullKeyName); + + // Default docking value + Q3DStudio::CString theDockString = + thePrefs.GetStringValue(PALETTE_CONTROL_DOCKID, L"0"); // left + long theDockId = ::atol(theDockString.GetCharStar()); + + // Default Rect + QRect theWindowRect; + Q3DStudio::CString theRectString = + thePrefs.GetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0"); + CStringTokenizer theRectTokenizer(theRectString, L","); + for (long theIndex = 0; theRectTokenizer.HasNextPartition(); + ++theRectTokenizer, ++theIndex) { + Q3DStudio::CString theCurrentString = theRectTokenizer.GetCurrentPartition(); + long theCurrentItem = ::atol(theCurrentString.GetCharStar()); + + switch (theIndex) { + case 0: + theWindowRect.setLeft(theCurrentItem); + break; + case 1: + theWindowRect.setTop(theCurrentItem); + break; + case 2: + theWindowRect.setRight(theCurrentItem); + break; + case 3: + theWindowRect.setBottom(theCurrentItem); + break; + }; + } + + // Palette id + Q3DStudio::CString thePaletteIdString = + thePrefs.GetStringValue(PALETTE_CONTROL_PALETTEID, L"0"); + long thePaletteId = ::atol(thePaletteIdString.GetCharStar()); + + // Read the selected item + Q3DStudio::CString theSelectedString = + thePrefs.GetStringValue(PALETTE_CONTROL_SELECTED, L"0"); + long theSelectedType = ::atol(theSelectedString.GetCharStar()); + + // Grab the palette + CMasterControl *theMasterControl; + if (thePaletteId) + theMasterControl = FindMasterByPaletteId(thePaletteId); + else + theMasterControl = FindUnusedMaster(); + + if (theMasterControl != nullptr) { + CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theMasterControl); + + Q3DStudio::CString theContentString = + thePrefs.GetStringValue(PALETTE_CONTROL_LIST, L"0"); + CStringTokenizer theTokenizer(theContentString, L","); + for (; theTokenizer.HasNextPartition(); ++theTokenizer) { + Q3DStudio::CString theCurrentString = theTokenizer.GetCurrentPartition(); + long theCurrentItem = ::atol(theCurrentString.GetCharStar()); + + if (theCurrentItem != CONTROLTYPE_NONE) + AddControlToMaster(theMasterControl, theCurrentItem); + } + + // Dock the bar in the appropriate location (if requested) + if (theDockId != 0) { + CDockBar *theDockBar = + (CDockBar *)m_MainFrame->GetControlBar(theDockId + AFX_IDW_DOCKBAR_TOP); + theDockBar->ClientToScreen(theWindowRect); + + thePaletteBar->SetHorz(CSize(theWindowRect.Width(), theWindowRect.Height())); + thePaletteBar->SetVert(CSize(theWindowRect.Width(), theWindowRect.Height())); + + m_MainFrame->DockControlBar(thePaletteBar, theDockBar, theWindowRect); + m_MainFrame->RecalcLayout(TRUE); + } + + // Select the old item + theMasterControl->SelectControl(theSelectedType); + + // Turn on my heart light + thePaletteBar->ShowPalette(true); + } + + // Move on to the next key + theCurrentPalette++; + } + + if (m_MainFrame) { + // Allow the control bars (docking palettes, etc) the opportunity to restore + // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which + // is different than CPreferences (".../Qt 3D Studio/Settings/...") + CSizingControlBar::GlobalLoadState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME); + m_MainFrame->LoadBarState(PALETTE_LAYOUT_KEY_NAME); + } +#endif + + return true; +} + +//============================================================================== +/** + * Save the palette state to the registry + */ +void CPaletteManager::Save() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Destroy current information in the prefs + CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY); + theMasterPrefs.Clear(); + + // Iterate through the m_MasterList + TMasterList::iterator theIterator = m_MasterList.begin(); + TMasterList::iterator theEndIterator = m_MasterList.end(); + for (long theMasterIndex = 0; theIterator != theEndIterator; ++theIterator) { + TSMasterInfo &theMasterInfo = *theIterator; + if (theMasterInfo.m_PaletteBar->IsVisible()) { + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%ls\\%ls%ld", PALETTE_KEY, PALETTE_SUBKEY, theMasterIndex); + + CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName); + + // Save palette contents + Q3DStudio::CString theTempString; + Q3DStudio::CString theContentString; + for (long theIndex = 0; theIndex < (long)theMasterInfo.m_Palettes.size(); ++theIndex) { + if (theMasterInfo.m_Palettes[theIndex]) { + theTempString.Format(L"%ld,", theIndex); + theContentString += theTempString; + } + } + + thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theContentString); + + // Save palette id + CControlBarInfo theBarInfo; + theMasterInfo.m_PaletteBar->GetBarInfo(&theBarInfo); + theTempString.Format(L"%ld", theBarInfo.m_nBarID); + thePrefs.SetStringValue(PALETTE_CONTROL_PALETTEID, theTempString); + + // Save selected item + long theSelectedIndex = theMasterInfo.m_Master->GetActiveIndex(); + theTempString.Format(L"%ld", theSelectedIndex); + thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theTempString); + + // Default values + thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, L"0"); + thePrefs.SetStringValue(PALETTE_CONTROL_RECT, L"0,0,0,0"); + + // Increment the palette counter + ++theMasterIndex; + } + } + + // Allow the control bars (docking palettes, etc) the opportunity to store + // This will use a registry key based off of AFX_IDS_APP_TITLE ("Qt 3D Studio") which + // is different than CPreferences (".../Qt 3D Studio/Settings/...") + if (m_MainFrame) { + CSizingControlBar::GlobalSaveState(m_MainFrame, PALETTE_LAYOUT_KEY_NAME); + m_MainFrame->SaveBarState(PALETTE_LAYOUT_KEY_NAME); + } +#endif +} + +//============================================================================== +// Defaults +//============================================================================== + +//============================================================================== +/** + * Set the palettes to the default state + * + * CONTROLTYPE_ACTION = 1, ///< + * CONTROLTYPE_BASICOBJECTS = 3, ///< + * CONTROLTYPE_INSPECTOR = 4, ///< + * CONTROLTYPE_SLIDE = 6, ///< + * CONTROLTYPE_TIMELINE = 7, ///< + * CONTROLTYPE_COMMAND = 8, ///< + * CONTROLTYPE_PROJECT = 9, ///< + * + * #define AFX_IDW_DOCKBAR_TOP 0xE81B = 0 + * #define AFX_IDW_DOCKBAR_LEFT 0xE81C = 1 + * #define AFX_IDW_DOCKBAR_RIGHT 0xE81D = 2 + * #define AFX_IDW_DOCKBAR_BOTTOM 0xE81E = 3 + * #define AFX_IDW_DOCKBAR_FLOAT 0xE81F = 4 + */ +void CPaletteManager::RestoreDefaults(bool inForce) +{ + Q_UNUSED(inForce); +#ifdef KDAB_TEMPORARILY_REMOVED + + // Destroy current information in the prefs (Palettes) + CPreferences theMasterPrefs = CPreferences::GetUserPreferences(PALETTE_KEY); + theMasterPrefs.Clear(); + + // "3,9,2,5:0:2:0,0,300,250#4,1:0:2:0,251,300,601#6:0:1:0,0,125,125#7:0:3:0,0,250,300"; + Q3DStudio::CString thePaletteString = ::LoadResourceString(IDS_DEFAULT_PALETTE_LAYOUT); + CStringTokenizer thePaletteTokenizer(thePaletteString, L"#"); + for (long thePaletteIndex = 0; thePaletteTokenizer.HasNextPartition(); + ++thePaletteTokenizer, ++thePaletteIndex) { + Q3DStudio::CString theCurrentPalette = thePaletteTokenizer.GetCurrentPartition(); + CStringTokenizer theSubTokenizer(theCurrentPalette, L":"); + + // No error checking, this string better be right! + Q3DStudio::CString theControlList = theSubTokenizer.GetCurrentPartition(); + ++theSubTokenizer; + Q3DStudio::CString theSelectedControl = theSubTokenizer.GetCurrentPartition(); + ++theSubTokenizer; + Q3DStudio::CString theDockId = theSubTokenizer.GetCurrentPartition(); + ++theSubTokenizer; + Q3DStudio::CString theControlRect = theSubTokenizer.GetCurrentPartition(); + ++theSubTokenizer; + + // Create the new registry keys (Palettes\PaletteN) + Q3DStudio::CString theSubKeyName; + theSubKeyName.Format(L"%ls\\%s%ld", PALETTE_KEY, PALETTE_SUBKEY, thePaletteIndex); + CPreferences thePrefs = CPreferences::GetUserPreferences(theSubKeyName); + + thePrefs.SetStringValue(PALETTE_CONTROL_LIST, theControlList); + thePrefs.SetStringValue(PALETTE_CONTROL_SELECTED, theSelectedControl); + thePrefs.SetStringValue(PALETTE_CONTROL_DOCKID, theDockId); + thePrefs.SetStringValue(PALETTE_CONTROL_RECT, theControlRect); + } +#endif + // Load these items + Load(); +} + +//============================================================================== +// Palette Context Menu +//============================================================================== + +//============================================================================= +/** + * Callback to create a new palette of the specified type. + */ +void CPaletteManager::OnNewPalette(CMasterControl *inMaster) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + ASSERT(inMaster != nullptr); + + // Query the current control type + long theType = inMaster->GetActiveType(); + + // Add a new master with that control type + CMasterControl *theNewMaster = AddMasterPalette(theType); + + // Float the new palette + CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(theNewMaster); + m_MainFrame->FloatControlBar(thePaletteBar, QPoint(0, 0)); + + // Turn on my heart light + thePaletteBar->ShowPalette(true); +#endif +} + +//============================================================================= +/** + * Callback to move a control to the specified palette + */ +void CPaletteManager::OnMovePalette(CMasterControl *inMoveFromMaster, + CMasterControl *inMoveToMaster) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + ASSERT(inMoveFromMaster != nullptr); + ASSERT(inMoveToMaster != nullptr); + + // Move the control to the new master + long theType = inMoveFromMaster->GetActiveType(); + AddControlToMaster(inMoveToMaster, theType); + + // Check to see if the master is empty + if (inMoveFromMaster->GetControlCount() <= 0) { + // Make sure the palette is visible + CStudioPaletteBar *thePaletteBar = FindStudioPaletteBar(inMoveFromMaster); + thePaletteBar->ShowPalette(false); + } +#endif +} + +//============================================================================== +// IMasterControlProvider +//============================================================================== + +void CPaletteManager::OnControlRemoved(CMasterControl *inMaster) +{ + (void)inMaster; +} + +void CPaletteManager::OnContextMenu(CMasterControl *inMaster, const CPt &inPosition, + CContextMenu *inMyMenu) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + CPaletteContextMenu theContextMenu(this, inMaster, inMyMenu); + + // Popup the context menu + inMaster->DoPopup(&theContextMenu, inPosition); +#endif +} + +void CPaletteManager::OnControlSelected(CMasterControl *inMaster, CControl *, long inType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + Q3DStudio::CString theControlName = GetControlName(inType); + + CStudioPaletteBar *thePalette = FindStudioPaletteBar(inMaster); + ASSERT(thePalette != nullptr); + + thePalette->SetWindowText(theControlName); +#endif +} + +//============================================================================== +// Static Methods +//============================================================================== + +//============================================================================== +/** + * Query the name of the specified palette + */ +Q3DStudio::CString CPaletteManager::GetControlName(long inType) +{ + switch (inType) { + case CONTROLTYPE_ACTION: + return ::LoadResourceString(IDS_PALETTE_ACTION); + case CONTROLTYPE_BASICOBJECTS: + return ::LoadResourceString(IDS_PALETTE_BASIC_OBJECTS); + case CONTROLTYPE_INSPECTOR: + return ::LoadResourceString(IDS_PALETTE_INSPECTOR); + case CONTROLTYPE_SLIDE: + return ::LoadResourceString(IDS_PALETTE_SLIDE); + case CONTROLTYPE_TIMELINE: + return ::LoadResourceString(IDS_PALETTE_TIMELINE); + case CONTROLTYPE_PROJECT: + return ::LoadResourceString(IDS_PALETTE_PROJECT); + default: + return L"< Empty >"; + }; +} + diff --git a/src/Authoring/Studio/_Win/Palettes/PaletteManager.h b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h new file mode 100644 index 00000000..e162e7f7 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/PaletteManager.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_VIEW_MANAGER_H +#define INCLUDED_VIEW_MANAGER_H 1 + +//============================================================================== +// Includes +//============================================================================== +#include <bitset> +#include "MasterControl.h" +#include "TimelineControl.h" + +//============================================================================== +// Forwards +//============================================================================== +class CStudioApp; +class CMainFrame; +class CStudioPaletteBar; + +class QDockWidget; + +//============================================================================== +/** + * @class CPaletteManager + */ +class CPaletteManager : public IMasterControlProvider +{ +public: + // Do NOT change the order/values of this enum, these + // values are stored in the registry + enum EControlTypes { + CONTROLTYPE_NONE = 0, ///< + CONTROLTYPE_ACTION = 1, ///< + CONTROLTYPE_BASICOBJECTS = 3, ///< + CONTROLTYPE_INSPECTOR = 4, ///< + CONTROLTYPE_SLIDE = 6, ///< + CONTROLTYPE_TIMELINE = 7, ///< + CONTROLTYPE_PROJECT = 9, ///< + + CONTROLTYPE_MAXCONTROLS = 32, ///< the maximum number of palettes( a string of this length + ///is saved in the registry, changing this value will require + ///an upgrade process ) + }; + +public: + typedef std::bitset<CONTROLTYPE_MAXCONTROLS> TPaletteSet; + +protected: + typedef struct _TSMasterInfo + { + CStudioPaletteBar *m_PaletteBar; ///< pointer to the master palette bar + TPaletteSet m_Palettes; ///< the palettes contained by the master + CMasterControl *m_Master; ///< pointer to the master control + + } TSMasterInfo; + + typedef std::map<long, QDockWidget *> TControlMap; + typedef std::vector<CStudioPaletteBar *> TPaletteList; + typedef std::vector<TSMasterInfo> TMasterList; + +protected: + CMainFrame *m_MainFrame; ///< + TControlMap m_ControlList; ///< map of EControlTypes and CControl + TPaletteList m_PaletteList; ///< + TMasterList m_MasterList; ///< + + static long s_PaletteIDBase; ///< + +public: + CPaletteManager(CMainFrame *inMainFrame); + virtual ~CPaletteManager(); + + // Access + void AddControlToMaster(CMasterControl *inControl, long inType); + void RemoveControlFromMaster(CMasterControl *inControl, long inType); + CMasterControl *FindMasterPalette(long inType); + long GetMasterCount(); + CMasterControl *GetMaster(long inIndex); + void HideControl(long inType); + bool IsControlVisible(long inType) const; + void ShowControl(long inType); + void ToggleControl(long inType); + + QDockWidget *GetControl(long inType) const; ///< return corresponding Palette according to EControlTypes enum value + QWidget *getFocusWidget() const; + bool tabNavigateFocusedWidget(bool tabForward); + CTimelineControl *GetTimelineControl() const; + + // Commands + void OnNewPalette(CMasterControl *inMaster); + void OnMovePalette(CMasterControl *inMoveFromMaster, CMasterControl *inMoveToMaster); + + // Serialization + bool Load(); + void Save(); + + // Defaults + void RestoreDefaults(bool inForce = false); + + // IMasterControlProvider + void OnControlRemoved(CMasterControl *inControl) override; + void OnContextMenu(CMasterControl *inControl, const CPt &inPosition, + CContextMenu *inMyMenu) override; + void OnControlSelected(CMasterControl *inMaster, CControl *inNewControl, long inType) override; + + // Static Methods + static Q3DStudio::CString GetControlName(long inType); + +protected: + CMasterControl *AddMasterPalette(long inType); + + void Reset(); + CStudioPaletteBar *CreatePalette(); + + CMasterControl *FindUnusedMaster(); + CMasterControl *FindMasterByPaletteId(long inPaletteId); + + CStudioPaletteBar *FindStudioPaletteBar(long inType); + CStudioPaletteBar *FindStudioPaletteBar(CMasterControl *inMaster); + void OnAsyncDestroyWindow(CStudioPaletteBar *inWnd); +}; + +#endif // INCLUDED_VIEW_MANAGER_H diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp new file mode 100644 index 00000000..a9f1e546 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "ProgressPalette.h" +#include "StudioConst.h" +#include "ResourceCache.h" +#include "ResImage.h" +#include "ProgressView.h" + +//============================================================================= +/** + * Constructor + */ +CProgressPalette::CProgressPalette() +{ +} + +//============================================================================= +/** + * Destructor + */ +CProgressPalette::~CProgressPalette() +{ +} + +//============================================================================== +/** + * A wrapper around the CMiniFrameWnd::Create() method. + * Simplifies the create parameters for the palette bar. Overridden because + * the loading screen is different from all the other palettes. + * @return The result from the Create() call (FALSE if unsuccessful) + */ +BOOL CProgressPalette::Create(CString inTitle, CCreateContext *inCreateContext, + CWnd *inParent /* = nullptr */) +{ + CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_WAIT)); + BOOL theReturnValue = FALSE; + + // Add the title of the bar to the registry location. + m_DialogName = inTitle; + + // Get the rectangle that we want this splash screen to occupy in the middle of the screen + CPt theScreenSize = ::GetAvailableDisplaySize(); + CResImage *theImage = CResourceCache::GetInstance()->GetBitmap("progress-screen.png"); + CPt theImageSize = theImage->GetSize(); + long theTitleBarHeight = ::GetSystemMetrics(SM_CYCAPTION); + long theXPos = theScreenSize.x / 2 - theImageSize.x / 2; + long theYPos = theScreenSize.y / 2 - theImageSize.y / 2; + CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x, + theYPos + theImageSize.y + theTitleBarHeight); + + // Create the dialog. + theReturnValue = CFrameWnd::Create(theWndClass, inTitle, WS_POPUP | WS_CAPTION, theWindowRect, + inParent, nullptr, 0, inCreateContext); + + return theReturnValue; +} + +//============================================================================== +/** + * Sends a message to the view that the progress bar needs to be updated to a + * new percentage. + * @param inPercent New percent complete to be displayed + */ +void CProgressPalette::SetProgress(long inPercent) +{ + SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_PERCENT, + static_cast<LPARAM>(inPercent)); + Invalidate(); + UpdateWindow(); +} + +//============================================================================== +/** + * Sends a message to the view that the action text (saving/loading) needs to be changed. + * @param inFileName New file name to be displayed + */ +void CProgressPalette::SetActionText(const Q3DStudio::CString &inText) +{ + SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_ACTIONTEXT, + reinterpret_cast<LPARAM>(&inText)); +} + +//============================================================================== +/** + * Sends a message to the view that the file name being opened needs to be changed. + * @param inFileName New file name to be displayed + */ +void CProgressPalette::SetFileName(const Q3DStudio::CString &inFileName) +{ + SendMessageToDescendants(WM_STUDIO_LOADPROGRESS, CProgressView::PROGRESSUPDATE_FILENAME, + reinterpret_cast<LPARAM>(&inFileName)); +}
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h new file mode 100644 index 00000000..7d7cb357 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressPalette.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PROGRESS_PALETTE_H +#define INCLUDED_PROGRESS_PALETTE_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "StudioPaletteBar.h" +#include "ProgressCallback.h" + +//============================================================================= +/** + * Palette for the loading screen + */ +class CProgressPalette : public CStudioDialog, public IProgressCallback +{ +public: + CProgressPalette(); + virtual ~CProgressPalette(); + virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr); + void SetProgress(long inPercent); + void SetFileName(const Q3DStudio::CString &inFileName); + void SetActionText(const Q3DStudio::CString &inText); +}; +#endif // INCLUDED_PROGRESS_PALETTE_H
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp new file mode 100644 index 00000000..8b7e796c --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "ProgressView.h" +#include "WndControl.h" +#include "StudioApp.h" +#include "ProgressControl.h" + +//============================================================================== +// Message Maps, etc. +//============================================================================== +IMPLEMENT_DYNCREATE(CProgressView, CView) + +BEGIN_MESSAGE_MAP(CProgressView, CView) +//{{AFX_MSG_MAP(CProgressView) +ON_WM_SIZE() +ON_WM_ERASEBKGND() +//}}AFX_MSG_MAP +ON_MESSAGE(WM_STUDIO_INITIALIZE_PALETTES, OnInitializePalettes) +ON_MESSAGE(WM_STUDIO_LOADPROGRESS, OnUpdateProgress) +END_MESSAGE_MAP() + +//============================================================================= +/** + * Constructor: Protected because the view is always created dynamically. + * You must call Initialize() before trying to use this class. + */ +CProgressView::CProgressView() + : m_WndControl(nullptr) + , m_ProgressControl(nullptr) +{ +} + +//============================================================================= +/** + * Destructor + */ +CProgressView::~CProgressView() +{ + if (m_WndControl) { + m_WndControl->DestroyWindow(); + m_WndControl = nullptr; + + SAFE_DELETE(m_ProgressControl); + } +} + +//============================================================================== +/** + * Handles the WM_INITIALUPDATE message. Responsible for preparing the view + * before it is displayed for the first time. + */ +LRESULT CProgressView::OnInitializePalettes(WPARAM, LPARAM) +{ + if (!m_WndControl) { + m_ProgressControl = new CProgressControl; + m_WndControl = new CWndControl(m_ProgressControl); + m_ProgressControl->SetName("Progress Control"); + + if (!::IsWindow(m_WndControl->m_hWnd)) + m_WndControl->CreateEx(0, AfxRegisterWndClass(CS_DBLCLKS, LoadCursor(nullptr, IDC_WAIT), + (HBRUSH)GetStockObject(BLACK_BRUSH)), + L"LoadView", WS_CHILD | WS_VISIBLE | WS_MAXIMIZE, + CRect(0, 0, 200, 200), this, 100); + } + + return 0; +} + +//============================================================================== +/** + * Handles the WM_STUDIO_LOADPROGRESS message. Changes text displayed on the + * load control, depending on what we are trying to update. + * @param inwParam Should be an EProgressMessage to indicate what we are updating + * @param inlParam Depends on inwParam. If the message type is PROGRESSUPDATE_PERCENT, + * this parameter contains a long value indicating the percent. If the message + * type is PROGRESSUPDATE_FILENAME, this parameter contains a pointer to an + * Q3DStudio::CString, which is the name of the file that we are loading. + * @return 0 + */ +LRESULT CProgressView::OnUpdateProgress(WPARAM inwParam, LPARAM inlParam) +{ + EProgressMessage theMessageType = static_cast<EProgressMessage>(inwParam); + + switch (theMessageType) { + // Update the percentage completed + case PROGRESSUPDATE_PERCENT: { + long thePercent = (long)inlParam; + m_ProgressControl->SetProgress(thePercent); + } break; + + // Update the name of the file being loaded + case PROGRESSUPDATE_FILENAME: { + Q3DStudio::CString *theName = reinterpret_cast<Q3DStudio::CString *>(inlParam); + m_ProgressControl->SetFileName(*theName); + } break; + + // Update the text above the file name (loading or saving) + case PROGRESSUPDATE_ACTIONTEXT: { + Q3DStudio::CString *theText = reinterpret_cast<Q3DStudio::CString *>(inlParam); + m_ProgressControl->SetActionText(*theText); + } break; + + // Nothing to do in the default case + default: + break; + } + + return 0; +} + +//============================================================================= +/** + * Required by base class but does nothing since all drawing is handled by the + * child control. + */ +void CProgressView::OnDraw(CDC *inDC) +{ + Q_UNUSED(inDC); +} + +//============================================================================= +/** + * Resizes the wnd control to fill the whole view. + */ +void CProgressView::OnSize(UINT inType, int inX, int inY) +{ + CView::OnSize(inType, inX, inY); + if (::IsWindow(m_WndControl->GetSafeHwnd())) + m_WndControl->MoveWindow(0, 0, inX, inY); +} + +//============================================================================== +/** + * Tells the view to erase before redrawing. Overridden because erasing + * before each draw produces a flashing effect. + * @param inDC the DC to erase on. + * @return FALSE. + */ +BOOL CProgressView::OnEraseBkgnd(CDC *inDC) +{ + Q_UNUSED(inDC); + return FALSE; +} diff --git a/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h new file mode 100644 index 00000000..ed023c0c --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Progress/ProgressView.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PROGRESS_VIEW_H +#define INCLUDED_PROGRESS_VIEW_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +//============================================================================== +// Forwards +//============================================================================== +class CWndControl; +class CProgressControl; +class CStudioApp; + +//============================================================================= +/** + * Windows view encapsulating the splash screen. + */ +class CProgressView : public CView +{ +public: + /// Used to pass messages from the palette, down to this view + enum EProgressMessage { + PROGRESSUPDATE_PERCENT = 0, ///< Inidicates that the percentage displayed should be updated + PROGRESSUPDATE_FILENAME, ///< Indicates that the file name displayed should be updated + PROGRESSUPDATE_ACTIONTEXT, ///< Indicates that the text above the file name needs to be + ///updated + }; + + virtual void OnDraw(CDC *inDC); + virtual LRESULT OnInitializePalettes(WPARAM inwParam, LPARAM inlParam); + virtual LRESULT OnUpdateProgress(WPARAM inwParam, LPARAM inlParam); + +protected: + CWndControl *m_WndControl; + CProgressControl *m_ProgressControl; + + CProgressView(); ///< Constructor is protected because you can only create this view dynamically + DECLARE_DYNCREATE(CProgressView) + virtual ~CProgressView(); + afx_msg void OnSize(UINT inType, int inX, int inY); + afx_msg BOOL OnEraseBkgnd(CDC *inDC); + DECLARE_MESSAGE_MAP() +}; + +#endif // INCLUDED_PROGRESS_VIEW_H
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp new file mode 100644 index 00000000..112631e6 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "SplashPalette.h" +#include "SplashControl.h" // Just for getting the control's size; the view owns the real splash control + +//============================================================================= +/** + * Constructor + */ +CSplashPalette::CSplashPalette() +{ +} + +//============================================================================= +/** + * Destructor + */ +CSplashPalette::~CSplashPalette() +{ +} + +//============================================================================== +/** + * A wrapper around the CMiniFrameWnd::Create() method. + * Simplifies the create parameters for the palette bar. Overridden because + * the splash screen is different from all the other palettes. + * @return The result from the Create() call (FALSE if unsuccessful) + */ +BOOL CSplashPalette::Create(CString inTitle, CCreateContext *inCreateContext, + CWnd *inParent /* = nullptr */) +{ + CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW)); + BOOL theReturnValue; + + // Add the title of the bar to the registry location. + m_DialogName = inTitle; + + // Get the rectangle that we want this splash screen to occupy in the middle of the screen + CPt theScreenSize = GetAvailableDisplaySize(); + CSplashControl theSplashControl; // Just for getting the control's size; the view owns the real + // splash control + CPt theImageSize = theSplashControl.GetSize(); + long theXPos = theScreenSize.x / 2 - theImageSize.x / 2; + long theYPos = theScreenSize.y / 2 - theImageSize.y / 2; + CRect theWindowRect(theXPos, theYPos, theXPos + theImageSize.x, theYPos + theImageSize.y); + + // Create the dialog. + DWORD theFlags; +#ifdef DEBUG + theFlags = WS_EX_TOOLWINDOW; +#else + theFlags = WS_EX_TOOLWINDOW | WS_EX_TOPMOST; +#endif + // Create the palette bar. + theReturnValue = CFrameWnd::CreateEx(theFlags, theWndClass, inTitle, WS_POPUP, theWindowRect, + inParent, 0, inCreateContext); + + return theReturnValue; +} diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h new file mode 100644 index 00000000..5f11af0c --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashPalette.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_SPLASH_PALETTE_H +#define INCLUDED_SPLASH_PALETTE_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "StudioPaletteBar.h" + +//============================================================================= +/** + * Palette for the splash screen + */ +class CSplashPalette : public CStudioDialog /*CStudioPaletteBar*/ +{ +public: + CSplashPalette(); + virtual ~CSplashPalette(); + virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *inParent = nullptr); +}; +#endif // INCLUDED_SPLASH_PALETTE_H
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp new file mode 100644 index 00000000..fd78e604 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "SplashView.h" +#include "WidgetControl.h" +#include "StudioApp.h" +#include "SplashControl.h" + +//============================================================================= +/** + * Constructor: Protected because the view is always created dynamically. + * You must call Initialize() before trying to use this class. + */ +CSplashView::CSplashView(QWidget *parent) + : QWidget(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) + , m_WndControl(nullptr) + , m_SplashControl(nullptr) +{ + OnInitializePalettes(); +} + +//============================================================================= +/** + * Destructor + */ +CSplashView::~CSplashView() +{ + delete m_WndControl; + m_WndControl = nullptr; + + delete m_SplashControl; +} + +//============================================================================== +/** + * Handles the WM_INITIALUPDATE message. Responsible for preparing the view + * before it is displayed for the first time. + */ +void CSplashView::OnInitializePalettes() +{ + if (!m_WndControl) { + m_SplashControl = new CSplashControl; + m_WndControl = new WidgetControl(m_SplashControl, this); + m_SplashControl->SetName("Splash Control"); + + setFixedSize(m_WndControl->sizeHint()); + } +} + +//============================================================================= +/** + * Resizes the wnd control to fill the whole view. + */ +void CSplashView::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + m_WndControl->setGeometry(rect()); +} diff --git a/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h new file mode 100644 index 00000000..28498e95 --- /dev/null +++ b/src/Authoring/Studio/_Win/Palettes/Splash/SplashView.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_SPLASH_VIEW_H +#define INCLUDED_SPLASH_VIEW_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +#include <QWidget> + +//============================================================================== +// Forwards +//============================================================================== +class WidgetControl; +class CSplashControl; + +//============================================================================= +/** + * Windows view encapsulating the splash screen. + */ +class CSplashView : public QWidget +{ +public: + explicit CSplashView(QWidget *parent = nullptr); + ~CSplashView(); + +protected: + void resizeEvent(QResizeEvent *event) override; + +public: + void OnInitializePalettes(); + +protected: + WidgetControl *m_WndControl; + CSplashControl *m_SplashControl; +}; + +#endif // INCLUDED_SPLASH_VIEW_H diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.cpp b/src/Authoring/Studio/_Win/Studio/stdafx.cpp new file mode 100644 index 00000000..b6cac561 --- /dev/null +++ b/src/Authoring/Studio/_Win/Studio/stdafx.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// stdafx.cpp : source file that includes just the standard includes +// Studio.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h"
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Studio/stdafx.h b/src/Authoring/Studio/_Win/Studio/stdafx.h new file mode 100644 index 00000000..8fb2d134 --- /dev/null +++ b/src/Authoring/Studio/_Win/Studio/stdafx.h @@ -0,0 +1,221 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifdef __cplusplus +#pragma once + +#pragma warning(disable : 4819) + +#include "UICMacros.h" + +//#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define VC_EXTRALEAN // Exclude morerarely-used stuff from Windows headers + +// Modify the following defines if you have to target a platform prior to the ones specified below. +// Refer to MSDN for the latest info on corresponding values for different platforms. + +#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit +#define _AFX_ALL_WARNINGS // turns off MFC's hiding of some common and often safely ignored warning + // messages + +#ifdef DEBUG +#define CHECK_BOUNDS // CHECK_BOUNDS affects the way an item is retrieved from container objects +#endif + +#if _MSC_VER >= 1400 +#if defined _M_IX86 +#pragma comment( \ + linker, \ + "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment( \ + linker, \ + "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment( \ + linker, \ + "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment( \ + linker, \ + "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#endif + +//============================================================================== +// Standard Includes +//============================================================================== +#include <stdio.h> // Standard includes MUST come first +#include <stdlib.h> +#include <float.h> +#include <math.h> + +//============================================================================== +// STL Includes +//============================================================================== +#pragma warning(push, 3) // Temporarily pop to warning level 3 while including standard headers +#pragma warning(disable : 4018) // Disable mismatched < STL warning +#include <vector> +#include <map> +#include <deque> +#include <string> +#include <stack> +#include <set> +#include <list> +#include <utility> +#include <algorithm> +#include <stdexcept> +#include <limits> +#pragma warning(pop) // Pop out to previous warning level (probably level 4) + +//============================================================================== +// MFC Includes +//============================================================================== +#pragma warning(push, 1) +#include <afxwin.h> // MFC core and standard components +#include <afxext.h> // MFC extensions +#include <afxdisp.h> // MFC Automation classes +#include <afxpriv.h> // AFX Windows Messages (WM_INITIALUPDATE for example) +#include <afxdtctl.h> // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include <afxcmn.h> // MFC support for Windows Common Controls +#include <atlbase.h> +#include <atlcom.h> +#endif // _AFX_NO_AFXCMN_SUPPORT + +//============================================================================== +// ATL Includes +//============================================================================== +#include "atlbase.h" // For CrystalEdit +#include "afxtempl.h" // For CrystalEdit +#include "afxole.h" // For CrystalEdit +#pragma warning(pop) + +// I put these in to help with some of the data model compile times. +#pragma warning(push) +#pragma warning(disable : 4100) +#pragma warning(disable : 4512) +#pragma warning(disable : 4702) +#pragma warning(disable : 4996) +#include <boost/function.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/variant.hpp> +#include <boost/scoped_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/bind.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/signals.hpp> +#include <boost/signals/connection.hpp> +#pragma warning(pop) + +//============================================================================== +// Disable certain warnings since warnings are errors +//============================================================================== +#pragma warning(disable : 4100) // unreferenced formal parameter +#pragma warning(disable : 4702) // Unreachable code +#pragma warning(disable : 4290) // C++ Exception Specification ignored +#pragma warning(disable : 4514) // Unreferenced inline function +#pragma warning(disable : 4121) // Alignment of member sensative to packing +#pragma warning(disable : 4512) // Assignment not generated +#pragma warning(disable : 4355) // This used in member initializer list. +#pragma warning(disable : 4127) // conditional expression is constant +#pragma warning(disable : 4189) // local variable is initialized but not referenced + +//============================================================================== +// Common Includes +//============================================================================== +#include "GUIDUtilities.h" +#include "UICId.h" + +//============================================================================== +// Application Includes (Aug '08 accumulated most popular include files) +//============================================================================== +#include "UICString.h" +#include "UICMath.h" +#include "StringLoader.h" +#include "StudioException.h" +#include "UICExceptions.h" +#include "Exceptions.h" +#include "UICObjectCounter.h" +#include "STLHelpers.h" +#include "Pt.h" +#include "Rct.h" +#include "SafeArray.h" +#include "PlatformMacros.h" +#include "PlatformTypes.h" +#include "Multicaster.h" +#include "GenericFunctor.h" +#include "CColor.h" +#include "InputStream.h" +#include "OutputStream.h" +#include "StudioUtils.h" +#include "StudioDefs.h" +#include "StudioErrorIDs.h" +#include "Strings.h" +#include "StudioPreferences.h" +#include "Renderer.h" +#include "StudioObjectTypes.h" +#include "HotKeys.h" +#include "Dispatch.h" +#include "Cmd.h" +#include "MasterP.h" +#include "Dialogs.h" +#include "Views.h" +#include "ResourceCache.h" +#include "CmdBatch.h" +#include "DispatchListeners.h" +#include "UICFile.h" +#include "StudioConst.h" +#include "resource.h" +#include "StudioProjectSettings.h" +#include "Preferences.h" +#include "StudioClipboard.h" +#include "DropTarget.h" +#include "ContextMenu.h" +#include "TextButton.h" + +#include "StudioPrefixWin32.h" + +//============================================================================== +// Common Includes +//============================================================================== +#include "Resource.h" + +//============================================================================== +// OpenGL Includes +//============================================================================== +#include <GL/gl.h> + +#define UIC_LITTLE_ENDIAN + +#define SAFE_DELETE(ptr) \ + if ((ptr) != nullptr) { \ + delete (ptr); \ + (ptr) = nullptr; \ + } +#endif diff --git a/src/Authoring/Studio/_Win/UI/ContextMenu.cpp b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp new file mode 100644 index 00000000..6aedc806 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ContextMenu.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 1999-2001 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "ContextMenu.h" +#include "StringLoader.h" + +//============================================================================= +/** + * Constructor + */ +CContextMenu::CContextMenu() + : m_SelectedOption(-1) + , m_IndexBase(0) +{ + m_Menu = ::CreatePopupMenu(); +} + +//============================================================================= +/** + * Destructor + */ +CContextMenu::~CContextMenu() +{ + ::DestroyMenu(m_Menu); +} + +//============================================================================= +/** + * Display the popup menu and perform the actions for whatever choice the + * user makes. + * @param inLocation the screen coordinates of the location to display this menu. + * @param inParentWindow the window to attach this menu to. + */ +long CContextMenu::DoPopup(CPt inLocation, HWND inParentWindow) +{ + // Allow derived classes to update the menu state + Update(); + + ::SetCursor(::LoadCursor(nullptr, IDC_ARROW)); + + // Display the menu and get the user's input + unsigned int theCommandID = (unsigned int)::TrackPopupMenuEx( + m_Menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY | TPM_RIGHTBUTTON, + inLocation.x, inLocation.y, inParentWindow, nullptr); + + // If an option was selected then get the performer for that option and execute it. + m_SelectedOption = theCommandID - 1; + if (m_SelectedOption >= 0) { + CContextMenuPerformer *thePerformer = GetSelectedMenuPerformer(m_SelectedOption); + if (thePerformer != nullptr) { + thePerformer->OnOptionSelected(); + } + } + + return m_SelectedOption; +} + +//============================================================================= +/** + * Append a separator to the list of items in this menu. + */ +void CContextMenu::AddSeparator() +{ + ::AppendMenu(m_Menu, MF_SEPARATOR, 0, nullptr); +} + +//============================================================================= +/** + * Append the option onto the end of this menu. + * @param inOptionNameStringID ID indicating the display name for the option. + * @param inPerformer the performer to be called if this option is selected. + * @param inIsEnabled false if the option is to be grayed out and disabled. + */ +void CContextMenu::AddOption(int inOptionNameStringID, CContextMenuPerformer *inPerformer, + bool inIsEnabled /* = true */) +{ + Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID)); + AddOption(theOptionName, inPerformer, inIsEnabled); +} + +//============================================================================= +/** + * Append the option onto the end of this menu. + * @param inOptionName the display name for the option. + * @param inPerformer the performer to be called if this option is selected. + * @param inIsEnabled false if the option is to be grayed out and disabled. + */ +void CContextMenu::AddOption(const Q3DStudio::CString &inOptionName, + CContextMenuPerformer *inPerformer, bool inIsEnabled /*= true */) +{ + size_t theIndex = m_IndexBase; // start from a base, so that submenu items can be distinguished + + long theFlags = MF_STRING; + if (!inIsEnabled) + theFlags |= MF_GRAYED; + + m_Performers.push_back(inPerformer); + m_Options.push_back(inOptionName); + CContextMenu *theSubMenu = (inPerformer ? inPerformer->GetSubMenu() : nullptr); + if (!theSubMenu) + theIndex += m_Performers.size(); + else // if performer has a submenu. + { + theIndex = (UINT)theSubMenu->GetMenuHandle(); + theFlags |= MF_POPUP; + } + + ::AppendMenuW(m_Menu, theFlags, theIndex, inOptionName); +} + +//============================================================================= +/** + * Remove all options from the menu. + */ +void CContextMenu::Clear() +{ + long theCount = ::GetMenuItemCount(m_Menu); + for (long theIndex = theCount - 1; theIndex >= 0; theIndex--) + ::DeleteMenu(m_Menu, theIndex, MF_BYPOSITION); + + m_Performers.clear(); + m_Options.clear(); +} + +//============================================================================= +/** + * Delete all the performers on this object. + * This is an ease of use method for subclasses if they allocated their + * performers on the heap. This just deletes all of them and clears the list. + */ +void CContextMenu::DeletePerformers() +{ + TPerformerList::iterator thePos = m_Performers.begin(); + for (; thePos != m_Performers.end(); ++thePos) { + delete (*thePos); + } + m_Performers.clear(); +} + +//============================================================================= +/** + * Adds or removes a check mark from the specified item. + * @param inIndex Index of context menu item to be edited + * @param inChecked true to set a check, false to remove a check + */ +void CContextMenu::SetCheck(long inIndex, bool inChecked) +{ + long theFlags = MF_BYPOSITION; + theFlags |= inChecked ? MF_CHECKED : MF_UNCHECKED; + + long theActualIndex = inIndex; + for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu) && thePos <= inIndex; + ++thePos) { + // Account for separators that doesn't "contribute" to the number of performers. + MENUITEMINFO theMenuInfo; + ZeroMemory(&theMenuInfo, sizeof(MENUITEMINFO)); + theMenuInfo.cbSize = sizeof(MENUITEMINFO); + theMenuInfo.fMask = MIIM_TYPE; + ::GetMenuItemInfo(m_Menu, thePos, TRUE, &theMenuInfo); + if (theMenuInfo.fType & MFT_SEPARATOR) + ++theActualIndex; + } + ::CheckMenuItem(m_Menu, theActualIndex, theFlags); +} + +//============================================================================= +/** + * Set all the menu items to being unchecked. + * This will uncheck any items that are currently checked. + */ +void CContextMenu::ClearChecked() +{ + for (long thePos = 0; thePos < (long)::GetMenuItemCount(m_Menu); ++thePos) + ::CheckMenuItem(m_Menu, thePos, MF_BYPOSITION | MF_UNCHECKED); +} + +//============================================================================= +/** + * Gets the string located at a certain index in the context menu list. Index + * is zero-based. + * @param inIndex zero-based index of the item whose string you want + * @return the string at the specified index + */ +Q3DStudio::CString CContextMenu::GetStringAt(long inIndex) +{ + Q3DStudio::CString theString; + if (inIndex >= 0 && inIndex < (long)m_Options.size()) + theString = m_Options.at(inIndex); + return theString; +} + +//============================================================================= +/** + * @return the number of items in this context menu + */ +long CContextMenu::GetItemCount() +{ + return (long)m_Options.size(); +} + +//============================================================================= +/** + * Override this to set enable state of options before the menu pops up + */ +void CContextMenu::Update() +{ +} + +static inline long GetEnableMenuItemFlags(bool inEnabledState) +{ + return MF_BYPOSITION | (inEnabledState ? (MF_ENABLED) : (MF_GRAYED)); +} + +void CContextMenu::EnableOptionByIndex(long inIndex, bool inEnabledState /*= true*/) +{ + if (inIndex >= 0 && inIndex < (long)m_Options.size()) + ::EnableMenuItem(m_Menu, inIndex, GetEnableMenuItemFlags(inEnabledState)); +} + +void CContextMenu::EnableOption(const Q3DStudio::CString &inOptionName, bool inEnabledState) +{ + long theCount = (long)m_Options.size(); + for (long theIndex = 0; theIndex < theCount; ++theIndex) { + if (m_Options[theIndex] == inOptionName) { + ::EnableMenuItem(m_Menu, theIndex, GetEnableMenuItemFlags(inEnabledState)); + break; + } + } +} + +void CContextMenu::EnableOption(unsigned int inOptionNameStringID, bool inEnabledState) +{ + Q3DStudio::CString theOptionName(::LoadResourceString(inOptionNameStringID)); + EnableOption(theOptionName, inEnabledState); +} + +//============================================================================= +/** + * Find the menu performer associated with this index, recursing down any submenu if necessary. + * @param inIndex index of the menu performer + */ +CContextMenuPerformer *CContextMenu::GetSelectedMenuPerformer(long inIndex) +{ + if (inIndex - m_IndexBase < static_cast<long>(m_Performers.size())) { + m_SelectedOption = + inIndex - m_IndexBase; // update this for any references to the selected option + return m_Performers.at(m_SelectedOption); + } + // if not found, recurse down submenus + CContextMenuPerformer *theResult = nullptr; + TPerformerList::iterator theIter = m_Performers.begin(); + for (; theIter != m_Performers.end() && !theResult; ++theIter) { + CContextMenu *theSubMenu = (*theIter)->GetSubMenu(); + if (theSubMenu) + theResult = theSubMenu->GetSelectedMenuPerformer(inIndex); + } + return theResult; +}
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.cpp b/src/Authoring/Studio/_Win/UI/ControlButton.cpp new file mode 100644 index 00000000..d99ce639 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ControlButton.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "resource.h" +#include "ControlButton.h" +#include "MemoryDC.h" +#include "WinUtils.h" + +//============================================================================== +/* + * Constructor: Initializes the object. + */ +CControlButton::CControlButton() + : m_ImageUp(nullptr) + , m_ImageDown(nullptr) + , m_ImageDisabled(nullptr) + , m_ImageActive(nullptr) + , m_ImageMouseTrack(nullptr) + , m_ImageLimbo(nullptr) + , m_ActiveFlag(FALSE) + , m_HotTrackFlag(FALSE) + , m_MouseOverFlag(FALSE) + , m_ActiveDepressedFlag(FALSE) + , m_LimboEnabled(FALSE) + , m_LimboFlag(FALSE) + , m_SimpleFrame(TRUE) + , m_DrawFrame(TRUE) + , m_DepressFlag(FALSE) + , m_3DColorsFlag(FALSE) +{ + m_ImageOffset = CPoint(0, 0); + m_FillColor = GetSysColor(COLOR_WINDOW); + m_TransparentColor = RGB(255, 0, 255); + m_FillColor = GetSysColor(COLOR_3DFACE); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +CControlButton::~CControlButton() +{ +} + +BEGIN_MESSAGE_MAP(CControlButton, CButton) +//{{AFX_MSG_MAP(CControlButton) +ON_WM_MOUSEMOVE() +ON_WM_ERASEBKGND() +//}}AFX_MSG_MAP +ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave) +END_MESSAGE_MAP() + +//============================================================================== +/** + * Method to create the button + * + * @param inStyle Window style for the button + * @param inRect Bounding rectangle for the button + * @param inParentWnd Parent window for the button + * @param inID Child window ID for the button + * @param inDepressFlag + * @param inLimboEnabled Set to TRUE if this is a tri-state button (defaults to false). + *The third state is referred to as "limbo". + * Then use SetLimbo() to enter and leave the limbo state. + * + * @return Returns TRUE if the button was created + */ +BOOL CControlButton::Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID, + BOOL inDepressFlag, BOOL inLimboEnabled) +{ + m_DepressFlag = inDepressFlag; + m_LimboEnabled = inLimboEnabled; + + return CButton::Create(L"", inStyle /*| WS_BORDER*/ | BS_OWNERDRAW, inRect, inParentWnd, inID); +} + +//============================================================================== +/** + * Adds images to the button for the different button states. + * @param inTransparentColor RGB value of the transparency color used within the + *bitmaps. If there is no transparency color, + * set this to a value that does not appear in any of + *the images. + * @param inImageUp Image for the up state + * @param inImageDown Image for the down state + * @param inImageDisabled Image for the disabled state + * @param inImageActive Image for the active state + * @param inImageMouseTrack Image for hot mouse tracking + * @param inImageLimbo Image for "limbo" state (used for tri-state buttons) + */ +void CControlButton::AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown, + short inImageDisabled, short inImageActive, short inImageMouseTrack, + short inImageLimbo) +{ + if (inImageUp != 0) + m_ImageUp = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageUp), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + // You always need to have at least one valid image for a button + ASSERT(m_ImageUp != nullptr); + + if (inImageDown != 0) + m_ImageDown = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDown), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + if (inImageDisabled != 0) + m_ImageDisabled = + (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageDisabled), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + if (inImageActive != 0) + m_ImageActive = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageActive), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + if (inImageMouseTrack != 0) + m_ImageMouseTrack = + (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageMouseTrack), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + if (inImageLimbo != 0) + m_ImageLimbo = (HBITMAP)LoadImage(AfxGetResourceHandle(), MAKEINTRESOURCE(inImageLimbo), + IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + + m_TransparentColor = inTransparentColor; + + if (IsWindow(m_hWnd)) + this->Redraw(); +} + +//============================================================================== +/** + * SetImageOffset + * + * Sets an image drawing offset + * + * @param inOffset Offset for image from (0,0) + */ +void CControlButton::SetImageOffset(CPoint inOffset) +{ + m_ImageOffset = inOffset; +} + +//============================================================================== +/** + * SetActiveDepressed + * + * Sets the active depressed flag. If TRUE and this control is set to active, + * then the image will be displayed in a depressed state (for toggle items). + * + * @param inActiveDepressedFlag TRUE if the active state should be depressed + */ +void CControlButton::SetActiveDepressed(BOOL inActiveDepressedFlag) +{ + m_ActiveDepressedFlag = inActiveDepressedFlag; +} + +//============================================================================== +/** + * SetActive + * + * Sets the active state for the button + * + * @param inActiveState Active state for the button + */ +void CControlButton::SetActive(BOOL inActiveFlag) +{ + m_ActiveFlag = inActiveFlag; + + if (IsWindow(m_hWnd)) + this->Redraw(); +} + +//============================================================================== +/** + * GetActive + * + * Gets the active state for the button + * + * @param None + * + * @return Active state for the button + */ +BOOL CControlButton::GetActive() +{ + return m_ActiveFlag; +} + +//============================================================================== +/** + * DrawItem + * + * Handle the owner drawn button + * + * @param inDrawItemStruct DRAWITEMSTRUCT structure + */ +void CControlButton::DrawItem(LPDRAWITEMSTRUCT inDrawItemStruct) +{ + CDC *theDC; + CMemoryDC theMemDC; + BOOL theEnabledFlag; + BOOL theDownStateFlag; + HBITMAP theBitmap = m_ImageUp; + CRect theRect; + + theDC = GetDC(); + + // Get the bounding client rectangle + GetClientRect(theRect); + + theMemDC.Create(theDC, theRect); + + theDownStateFlag = (inDrawItemStruct->itemState & ODS_SELECTED); + + // Is this window enabled? + theEnabledFlag = IsWindowEnabled(); + + if (m_ActiveFlag) + theBitmap = m_ImageActive; + + if (m_MouseOverFlag) + if (m_ImageMouseTrack != 0) + theBitmap = m_ImageMouseTrack; + + if (!theEnabledFlag) { + // Disabled + if (m_ImageDisabled != 0) + theBitmap = m_ImageDisabled; + } else { + // Window is enabled + if (theDownStateFlag) + if (m_ImageDown != 0) + theBitmap = m_ImageDown; + } + + // If the button has limbo enabled, and it in limbo state, it overrides any previous button + // settings + if (m_LimboEnabled && m_LimboFlag) + if (m_ImageLimbo != 0) + theBitmap = m_ImageLimbo; + + // Fill the background color + theMemDC.FillSolidRect(theRect, m_FillColor); + + // Draw the bitmap if it exists + if (theBitmap) + CWinUtils::DrawTransparentBitmap( + &theMemDC, m_ImageOffset.x + theDownStateFlag * m_DepressFlag, + m_ImageOffset.y + theDownStateFlag * m_DepressFlag, theBitmap, m_TransparentColor); + + // Hot tracking the mouse over the button? + if (m_HotTrackFlag) { + if (m_DepressFlag) { + if (theDownStateFlag) + DrawButtonFrame((CDC *)&theMemDC, &theRect, TRUE); + else if (m_MouseOverFlag) + DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE); + } else { + if (m_MouseOverFlag) + DrawButtonFrame((CDC *)&theMemDC, &theRect, FALSE); + } + } else { + // Draw the frame around the button + if (!m_ActiveFlag) + DrawButtonFrame((CDC *)&theMemDC, &theRect, theDownStateFlag * m_DepressFlag); + } + + theMemDC.Release(); + + ReleaseDC(theDC); +} + +//============================================================================== +/** + * DrawButtonFrame + * + * Draw the button frame + * + * @param inDC Device context for drawing + * @param inRect Bounding rectangle for the button frame + * @param inDownFlag If TRUE, the button is down + */ +void CControlButton::DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag) +{ + if (m_DrawFrame) { + COLORREF theShadowColor = GetSysColor(COLOR_3DSHADOW); + COLORREF theHiliteColor = GetSysColor(COLOR_3DHIGHLIGHT); + + if (inDownFlag) { + theShadowColor = GetSysColor(COLOR_3DHIGHLIGHT); + theHiliteColor = GetSysColor(COLOR_3DSHADOW); + } + + CRect theFrameRect; + + theFrameRect.CopyRect(inRect); + + if (m_SimpleFrame) { + inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor); + } else { + if (inDownFlag) { + theFrameRect.right--; + theFrameRect.bottom--; + + inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor); + } else { + // the button is up + theFrameRect.right--; + theFrameRect.bottom--; + + inDC->Draw3dRect(&theFrameRect, theHiliteColor, theShadowColor); + + inDC->MoveTo(theFrameRect.right, theFrameRect.top); + inDC->LineTo(theFrameRect.right, theFrameRect.bottom); + inDC->LineTo(theFrameRect.left, theFrameRect.bottom); + } + } + } +} + +//============================================================================== +/** + * SetHotTrack + * + * Set the hot track (mouse over) flag + * + * @param inHotTrackFlag Hot tracking flag + */ +void CControlButton::SetHotTrack(BOOL inHotTrackFlag) +{ + m_HotTrackFlag = inHotTrackFlag; + + if (IsWindow(m_hWnd)) + this->Redraw(); +} + +//============================================================================== +/** + * OnMouseMove + * + * Handle the WM_MOUSEMOVE message + * + * @param inFlags Flags for WM_MOUSEMOVE + * @param inPoint Cursor position in client coordinates + */ +void CControlButton::OnMouseMove(UINT inFlags, CPoint inPoint) +{ + CButton::OnMouseMove(inFlags, inPoint); + + if (!m_MouseOverFlag) { + this->TrackMouse(); + m_MouseOverFlag = TRUE; + + this->Redraw(); + } +} + +//============================================================================== +/** + * OnMouseMove + * + * Handle the WM_MOUSELEAVE message + * + * @param inwParam WPARAM for the WM_MOUSELEAVE message + * @param inlParam LPARAM for the WM_MOUSELEAVE message + * + * @param Return code - returns TRUE if this message is processed. + */ +LRESULT CControlButton::OnMouseLeave(WPARAM inwParam, LPARAM inlParam) +{ + Q_UNUSED(inwParam); + Q_UNUSED(inlParam); + + m_MouseOverFlag = FALSE; + + this->TrackMouse(FALSE); + + this->Redraw(); + + return TRUE; +} + +//============================================================================== +/** + * TrackMouse + * + * Register for the WM_MOUSELEAVE message to determine when + * the mouse leaves this button. + * + * @param inTrackEnableFlag - TRUE/FALSE depending on whether we want to track the mouse + *event state. + */ +void CControlButton::TrackMouse(BOOL inTrackEnableFlag) +{ + TRACKMOUSEEVENT theTrackMouseEvent; + + memset(&theTrackMouseEvent, 0, sizeof(theTrackMouseEvent)); + + theTrackMouseEvent.cbSize = sizeof(theTrackMouseEvent); + theTrackMouseEvent.dwFlags = TME_LEAVE; + if (!inTrackEnableFlag) + theTrackMouseEvent.dwFlags |= TME_CANCEL; + theTrackMouseEvent.hwndTrack = m_hWnd; + + _TrackMouseEvent(&theTrackMouseEvent); +} + +//============================================================================== +/** + * Redraw + * + * Invalidate and update the button + * + * @param None + */ +void CControlButton::Redraw() +{ + // Invalidate and update the window + InvalidateRect(nullptr, TRUE); + UpdateWindow(); +} + +//============================================================================== +/** + * Handles the WM_ERASEBKGND message. This function is overridden so that we + * can prevent the background from being erased. When we draw the button, the + * background is filled in with the appropriate color. Actually erasing the + * background before a draw was producing flickering. + * + * @param pDC Not used. + */ +BOOL CControlButton::OnEraseBkgnd(CDC *pDC) +{ + Q_UNUSED(pDC); + return 1; +} diff --git a/src/Authoring/Studio/_Win/UI/ControlButton.h b/src/Authoring/Studio/_Win/UI/ControlButton.h new file mode 100644 index 00000000..6f168cb2 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ControlButton.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_) +#define AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CControlButton window + +class CControlButton : public CButton +{ + // Construction +public: + CControlButton(); + + // Attributes +public: +protected: + HBITMAP m_ImageUp, m_ImageDown, m_ImageDisabled, m_ImageActive, m_ImageMouseTrack, + m_ImageLimbo; // resource bitmap values for various button states + BOOL m_DepressFlag, m_3DColorsFlag; // drawing flags + BOOL m_ActiveFlag; // TRUE if the button is active (ie - selected) + BOOL m_ActiveDepressedFlag; // TRUE if the active state should be drawn depressed + CPoint m_ImageOffset; // Image offset from (0,0) + BOOL m_MouseOverFlag; // TRUE if the mouse is currently over this button + BOOL m_HotTrackFlag; // TRUE if the mouse should be hot-tracked + BOOL m_SimpleFrame; // TRUE if the button is a simple frame + BOOL m_DrawFrame; // TRUE if the frame around the button should be drawn + BOOL m_LimboEnabled; ///< TRUE if this button is capable of being in limbo (decided at creation + ///time) + BOOL m_LimboFlag; ///< TRUE if the button is currently in limbo state + COLORREF m_FillColor; + COLORREF m_TransparentColor; + + // Operations +public: + void AddImages(COLORREF inTransparentColor, short inImageUp, short inImageDown = 0, + short inImageDisabled = 0, short inImageActive = 0, short inImageMouseTrack = 0, + short inImageLimbo = 0); + + BOOL Create(DWORD inStyle, const RECT &inRect, CWnd *inParentWnd, short inID, + BOOL inDepressFlag = TRUE, BOOL inTriState = FALSE); + + BOOL GetActive(); + + void SetActive(BOOL inActiveFlag); + void SetActiveDepressed(BOOL inActiveDepressedFlag); + /// Sets the "limbo" state of the button. Usefully for making tri-state buttons. Limbo state + /// only works if the limbo flag was set during creation. + void SetLimbo(BOOL inLimboFlag) { m_LimboFlag = inLimboFlag; } + /// Returns TRUE if the button is in "limbo" state + BOOL GetLimbo() { return m_LimboFlag; } + void SetHotTrack(BOOL inHotTrackFlag); + void SetImageOffset(CPoint inOffset); + void SetDrawFrame(BOOL inDrawFrame) { m_DrawFrame = inDrawFrame; } + /// Use this function to manually set the fill color behind the button. Use this if you notice + /// that the wrong color is showing up. + void SetFillColor(COLORREF inColor) { m_FillColor = inColor; } +protected: + void DrawButtonFrame(CDC *inDC, CRect *inRect, BOOL inDownFlag); + void Redraw(); + void TrackMouse(BOOL inTrackEnableFlag = TRUE); + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CControlButton) +public: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + //}}AFX_VIRTUAL + + // Implementation +public: + virtual ~CControlButton(); + + // Generated message map functions +protected: + //{{AFX_MSG(CControlButton) + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg BOOL OnEraseBkgnd(CDC *pDC); + //}}AFX_MSG + afx_msg LRESULT OnMouseLeave(WPARAM inwParam, LPARAM inlParam); + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONTROLBUTTON_H__6B61A743_FB7E_11D4_A87A_005004D48D91__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.cpp b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp new file mode 100644 index 00000000..13277385 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/CrashDlg.cpp @@ -0,0 +1,212 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== +#include "MainFrm.h" +#include "CrashDlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CCrashDlg dialog + +CCrashDlg::CCrashDlg(CWnd *pParent /*=nullptr*/) + : CDialog(CCrashDlg::IDD, pParent) + , m_Filename(_T("")) +{ + //{{AFX_DATA_INIT(CCrashDlg) + m_Header = _T(""); + //}}AFX_DATA_INIT + + m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName())); + + m_Color_Background = CStudioPreferences::GetDarkBaseColor(); + m_Color_Text = CStudioPreferences::GetMasterColor(); + m_Color_Gray = CStudioPreferences::GetNormalColor(); + m_Color_Dark = CStudioPreferences::GetInactiveColor(); +} + +void CCrashDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCrashDlg) + DDX_Control(pDX, IDC_CRASHICON, m_CrashIcon); + DDX_Text(pDX, IDC_HEADER, m_Header); + DDX_Text(pDX, IDC_HEADER2, m_FilenameSaved); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CCrashDlg, CDialog) +//{{AFX_MSG_MAP(CCrashDlg) +ON_BN_CLICKED(IDEXIT, OnExit) +//}}AFX_MSG_MAP +// ON_STN_CLICKED(IDC_HEADER, &CCrashDlg::OnStnClickedHeader) +ON_WM_ERASEBKGND() +ON_WM_CTLCOLOR() +ON_WM_DESTROY() +END_MESSAGE_MAP() + +//============================================================================== +/** + * Set the description of the crash. + * @param inErrorMessage the error message. + */ +//============================================================================== +void CCrashDlg::SetErrorMessage(CString inErrorMessage) +{ + m_ErrorMessage = inErrorMessage; +} + +//============================================================================== +/** + * Set the project filename saved + * @param inFilename the filename of the crashed project + */ +//============================================================================== +void CCrashDlg::SetFilename(CString inFilename) +{ + m_Filename = inFilename; +} + +//============================================================================== +/** + * Set the stack trace for the crash. + * @param inStackTrace the stack trace. + */ +//============================================================================== +void CCrashDlg::SetStackTrace(CString inStackTrace) +{ + m_StackTrace = inStackTrace; +} + +///////////////////////////////////////////////////////////////////////////// +// CCrashDlg message handlers + +void CCrashDlg::OnExit() +{ + this->EndDialog(0); + _exit(EXIT_FAILURE); +} + +void CCrashDlg::SplitLongPath(int controlId, CString &text) +{ + + // Get the device context of your control. + CDC *dc = GetDlgItem(controlId)->GetDC(); + CRect filenameTextRect; + GetDlgItem(controlId)->GetClientRect(filenameTextRect); + + HGDIOBJ hOldFont = dc->SelectObject(&m_MediumFont2); + + CRect tmpStringRect(0, 0, 0, 0); + CString workingString = text; + + CString tmpString; + std::vector<int> insertPosition; + int previousOffset = 0; + + for (int i = 0; i < workingString.GetLength(); ++i) { + tmpString = workingString.Mid(previousOffset, i - previousOffset); + dc->DrawText(tmpString, &tmpStringRect, DT_CALCRECT); + if (tmpStringRect.Width() + 5 > filenameTextRect.Width()) { + previousOffset = i; + insertPosition.push_back(i - 1); + } + } + + // adds in all the \n + for (int i = (int)insertPosition.size() - 1; i >= 0; --i) { + text.Insert(insertPosition[i], '\n'); + } + + dc->SelectObject(hOldFont); +} + +BOOL CCrashDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_Brush.CreateSolidBrush(m_Color_Background); + GetDlgItem(IDC_HEADER)->SetFont(&m_MediumFont2); + GetDlgItem(IDC_HEADER2)->SetFont(&m_MediumFont2); + + // m_Header = ::LoadResourceString( IDS_ERROR_MSGPASSING ).GetMulti( ); + m_Header = m_ErrorMessage; + m_FilenameSaved = m_Filename; + + CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE); + this->SetWindowText(theTitle); + + // Show the exclamation point icon + m_CrashIcon.SetIcon(::LoadIcon(nullptr, IDI_ERROR)); + + SplitLongPath(IDC_HEADER2, m_FilenameSaved); + SplitLongPath(IDC_HEADER, m_Header); + + this->UpdateData(FALSE); + + return TRUE; +} + +BOOL CCrashDlg::OnEraseBkgnd(CDC *pDC) +{ + CRect theClientRect; + GetClientRect(&theClientRect); + pDC->FillSolidRect(theClientRect, m_Color_Background); + + return TRUE; +} + +HBRUSH CCrashDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT) +{ + int theCtrlID = pWnd->GetDlgCtrlID(); + if (theCtrlID == IDREPORT || theCtrlID == IDEXIT || theCtrlID == IDC_LINE_CRASHDLG) { + pDC->SetBkMode(TRANSPARENT); // for area just behind the text + pDC->SetTextColor(m_Color_Text); + } else if (theCtrlID == IDC_HEADER || theCtrlID == IDC_HEADER2) { + pDC->SetBkMode(TRANSPARENT); // for area just behind the text + pDC->SetTextColor(m_Color_Gray); + } + + return m_Brush; +} + +void CCrashDlg::OnDestroy() +{ + CDialog::OnDestroy(); + + m_Brush.DeleteObject(); +} diff --git a/src/Authoring/Studio/_Win/UI/CrashDlg.h b/src/Authoring/Studio/_Win/UI/CrashDlg.h new file mode 100644 index 00000000..75f5765c --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/CrashDlg.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_CRASH_DIALOG_H +#define INCLUDED_CRASH_DIALOG_H +#include "afxwin.h" +#include <string.h> + +#pragma once + +///////////////////////////////////////////////////////////////////////////// +// CCrashDlg dialog + +class CCrashDlg : public CDialog +{ + // Construction +public: + CCrashDlg(CWnd *pParent = nullptr); // standard constructor + + // Dialog Data + //{{AFX_DATA(CCrashDlg) + enum { IDD = IDD_CRASHDLG }; + CStatic m_CrashIcon; + CString m_Header; + //}}AFX_DATA + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCrashDlg) +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + // Implementation +public: + void SetErrorMessage(CString inErrorMessage); + void SetFilename(CString inFilename); + void SetStackTrace(CString inStackTrace); + void SplitLongPath(int controlId, CString &text); + +protected: + CString m_ErrorMessage; + CString m_FilenameSaved; + CString m_StackTrace; + + COLORREF m_Color_Background; + COLORREF m_Color_Text; + COLORREF m_Color_Gray; + COLORREF m_Color_Dark; + CBrush m_Brush; + CFont m_MediumFont2; + + // Generated message map functions + //{{AFX_MSG(CCrashDlg) + afx_msg void OnSave(); + afx_msg void OnExit(); + afx_msg void OnDestroy(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + afx_msg BOOL OnEraseBkgnd(CDC *pDC); + afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor); + CString m_Filename; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // INCLUDED_CRASH_DIALOG_H diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp new file mode 100644 index 00000000..7827ee93 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "Strings.h" + +//============================================================================== +// Includes +//============================================================================== +#include "EditCameraBar.h" +#include "MainFrm.h" +#include "SceneView.h" +#include "StringLoader.h" +#include "StudioPreferences.h" +#include "StudioApp.h" +#include "IStudioRenderer.h" + +#include <QComboBox> +#include <QLabel> + +//============================================================================== +/** + * Constructor + */ +CEditCameraBar::CEditCameraBar(QWidget* parent) + : QToolBar(parent) + , m_SceneView(nullptr) + , m_ActiveCameraIndex(-1) +{ + OnCustomizeToolbar(); + auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated); + connect(m_CameraSelector, activated, this, &CEditCameraBar::OnCameraChanged); +} + +//============================================================================== +/** + * Destructor + */ +CEditCameraBar::~CEditCameraBar() +{ + delete m_CameraSelector; + delete m_CameraText; +} + +//============================================================================== +/** + * Setup the list of edit cameras into the camera combo box + * @param inCameras the container that holds the edit cameras + */ +void CEditCameraBar::SetupCameras() +{ + m_CameraSelector->clear(); + Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer(); + QStringList theCameraNames; + theRenderer.GetEditCameraList(theCameraNames); + int idx = 1; + for (const QString &str : qAsConst(theCameraNames)) { + m_CameraSelector->addItem(str, QVariant((int)idx)); + idx++; + } + + m_CameraSelector->addItem("--------------------------"); + m_CameraSelector->setItemData(m_CameraSelector->count() - 1, -1); // set to an invalid pointer + m_CameraSelector->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString()); + m_CameraSelector->setItemData(m_CameraSelector->count() - 1, 0); + + long thePreferredView = CStudioPreferences::GetPreferredStartupView(); + long theNumItems = m_CameraSelector->count(); + if (thePreferredView == -1) // deployment view + { + m_CameraSelector->setCurrentIndex(theNumItems - 1); + HandleCameraChanged(theNumItems - 1); // set to the last one + } else { + int theIndex; + if (thePreferredView < theNumItems - 2) + theIndex = thePreferredView; + else // possibly from old content where cameras are removed + theIndex = 0; + m_CameraSelector->setCurrentIndex(theIndex); + HandleCameraChanged(theIndex); + } +} + +//============================================================================== +/** + * Callback method when the camera is changed from the camera selection combo box + */ +void CEditCameraBar::OnCameraChanged() +{ + HandleCameraChanged(m_CameraSelector->currentIndex()); +} + +//============================================================================== +/** + * Handle the switching of the current edit camera + * @param inIndex the index of the to-be-activated camera in the combo box + */ +void CEditCameraBar::HandleCameraChanged(int inIndex) +{ + Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer(); + QStringList theCameraNames; + theRenderer.GetEditCameraList(theCameraNames); + int theNumCameras = theCameraNames.size(); + if (inIndex < theNumCameras) { + theRenderer.SetEditCamera(inIndex); + m_ActiveCameraIndex = inIndex; + if (m_SceneView) + m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_EDIT); + } else if (inIndex > theNumCameras) { + theRenderer.SetEditCamera(-1); + m_ActiveCameraIndex = inIndex; + if (m_SceneView) + m_SceneView->SetViewMode(CPlayerContainerWnd::VIEW_SCENE); + } else { + m_CameraSelector->setCurrentIndex(m_ActiveCameraIndex); + } + if (m_SceneView) + m_SceneView->OnEditCameraChanged(); + + CMainFrame *theMainFrame = g_StudioApp.m_pMainWnd; + ASSERT(theMainFrame != nullptr); + + // if the current tool is camera rotate and has been switch to 2d camera + // set the tool to camera pan + if (theMainFrame != nullptr) { + long theToolMode = g_StudioApp.GetToolMode(); + if (theRenderer.DoesEditCameraSupportRotation(theRenderer.GetEditCamera()) == false + && theToolMode == STUDIO_TOOLMODE_CAMERA_ROTATE) { + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + m_SceneView->SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + } + + // Trigger for tool changed. Changing between deployment/edit camera can change the tool + theMainFrame->OnUpdateToolChange(); + } +} + +//============================================================================== +/** + * Set the current scene view. This scene view is notified when there is a camera + * changed. + * @param inSceneView the scene view object + */ +void CEditCameraBar::SetSceneView(CSceneView *inSceneView) +{ + m_SceneView = inSceneView; +} + +//============================================================================== +/** + * Enable/Disable the edit camera selector combo box. + * @param inFlag true to enable the camera selector combo box, false to disable + */ +void CEditCameraBar::Enable(bool inFlag) +{ + m_CameraSelector->setEnabled(inFlag); +} + +//============================================================================== +/** + * When the active camera is changed, the display string needs to be changed. Hence + * find which entry is the one which is modified and update with the new string + * @param inCamera the camera that has been modified + */ +void CEditCameraBar::OnEditCameraChanged() +{ + using qt3ds::QT3DSI32; + QT3DSI32 cameraIndex = g_StudioApp.GetRenderer().GetEditCamera(); + long theNumEntry = m_CameraSelector->count(); + for (long theIndex = 0; theIndex < theNumEntry; ++theIndex) { + if (m_CameraSelector->itemData(theIndex).toInt() == cameraIndex) { + if (theIndex != m_CameraSelector->currentIndex()) { + m_CameraSelector->setCurrentIndex(theIndex); + HandleCameraChanged(theIndex); + } + break; + } + } +} + +//============================================================================== +/** + * Callback while creating the toolbar in MainFrm. This allows the toolbar to add + * other controls to it. For this toolbar, we want to add a descriptor and a camera + * selector dropdown combobox. + */ +//============================================================================== +void CEditCameraBar::OnCustomizeToolbar() +{ + // Create the combo box + addWidget(m_CameraSelector = new QComboBox); + // We need to specify accessibleName and objectName for the combobox, as it's in the toolbar, + // and we want to use a different style for it. + m_CameraSelector->setAccessibleName(QStringLiteral("cameraSelector")); + m_CameraSelector->setObjectName(QStringLiteral("cameraSelector")); + m_CameraSelector->setMinimumWidth(145); +} diff --git a/src/Authoring/Studio/_Win/UI/EditCameraBar.h b/src/Authoring/Studio/_Win/UI/EditCameraBar.h new file mode 100644 index 00000000..bd8427f5 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/EditCameraBar.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_EDIT_CAMERA_BAR +#define INCLUDED_EDIT_CAMERA_BAR 1 + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//============================================================================== +// Includes +//============================================================================== +#include "DispatchListeners.h" +#include <vector> + +#include <QToolBar> + +QT_BEGIN_NAMESPACE +class QComboBox; +class QLabel; +QT_END_NAMESPACE + +//============================================================================== +// Forwards +//============================================================================== +class CSceneView; + +//============================================================================== +/** + * @class CEditCameraBar + */ +class CEditCameraBar : public QToolBar, public CEditCameraChangeListener +{ + Q_OBJECT +public: + CEditCameraBar(QWidget* parent = nullptr); // standard constructor + virtual ~CEditCameraBar(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditCameraBar) + //}}AFX_VIRTUAL + + // Implementation + // Generated message map functions + void OnCameraChanged(); + void OnCustomizeToolbar(); + +public: + void SetupCameras(); + void SetSceneView(CSceneView *inSceneView); + void Enable(bool inFlag); + void HandleCameraChanged(int inIndex); + + // CEditCameraChangeListener + void OnEditCameraChanged() override; + void OnEditCamerasTransformed() override {} // I am not interested in this + void OnAuthorZoomChanged() override {} + +protected: + CSceneView *m_SceneView; ///< The scene view object + long m_ActiveCameraIndex; ///< The index of the active camera in the list + + // UI Controls definition + QLabel* m_CameraText; ///< Static text showing the word "Camera" + QComboBox* m_CameraSelector; ///< Combo box for selecting edit camera +}; + +#endif diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.cpp b/src/Authoring/Studio/_Win/UI/EditorPane.cpp new file mode 100644 index 00000000..ef274392 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/EditorPane.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "EditorPane.h" + +//============================================================================== +/** + * Constructor: Creates a CEditorPane + */ +CEditorPane::CEditorPane() + : m_EditObject(nullptr) +{ +} + +//============================================================================== +/** + * Destructor: Releases the CEditorPane + */ +CEditorPane::~CEditorPane() +{ +} + +//============================================================================== +/** + * Set the object that this window will edit. + * Recieve and keep the CAsset to be edited. You can override this method + * for each specific editor view class. + * @param inEditObject The CAsset to be represented and edited in this view. + */ +void CEditorPane::SetEditObject(CAsset *inEditObject) +{ + // Retain this object + m_EditObject = inEditObject; +} + +//============================================================================== +/** + * Get the object that this window is editing. + * return The CAsset that is associated with this window + */ +CAsset *CEditorPane::GetEditObject() +{ + // Return the asset + return m_EditObject; +} + +//============================================================================== +/** + * CloseEditor: Close the editor. + * Override to close each individual editor. + * @return false + */ +bool CEditorPane::CloseEditor() +{ + return false; +}
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/UI/EditorPane.h b/src/Authoring/Studio/_Win/UI/EditorPane.h new file mode 100644 index 00000000..9bc91694 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/EditorPane.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_EDITOR_PANE +#define INCLUDED_EDITOR_PANE 1 + +#pragma once + +//============================================================================== +// Forwards +//============================================================================== +class CAsset; + +//============================================================================== +/** + * @class CEditorPane + * @brief Abstract base class for various editor views. + * + * A base class for universally accessing information from editor views. + */ +class CEditorPane +{ + // Fields +protected: + CAsset *m_EditObject; ///< object being edited by this window. + + // Methods +public: + CEditorPane(); + virtual ~CEditorPane(); + virtual void SetEditObject(CAsset *inEditObject); + CAsset *GetEditObject(); + virtual bool CloseEditor(); +}; + +#endif // INCLUDED_EDITOR_PANE
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp new file mode 100644 index 00000000..9183e536 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.cpp @@ -0,0 +1,451 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "stdafx.h" +#include "Strings.h" +#include <afxpriv.h> +#include "FileDialogEX.h" +#include "resource.h" +#include "windowsx.h" +#include "Userenv.h" +#include "Commdlg.h" +#include "CdErr.h" +#include "Preferences.h" + +static const long SFILELISTBUFFERSIZE = + 2048; // Size of the char buffer used to store selected filenames +// static BOOL IsWin2000(); + +///////////////////////////////////////////////////////////////////////////// +// CFileDialogEx + +IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog) + +//============================================================================== +/** + * CFileDialogEx: constructor + */ +//============================================================================== +CFileDialogEx::CFileDialogEx(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, + DWORD dwFlags, LPCTSTR lpszFilter, CWnd *pParentWnd) + : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) + , m_IsSaving(FALSE) + , m_LastFilterIndex(1) + , m_FileListBuffer(nullptr) + , m_WasCreateNewDirectoryChecked(false) + , m_CreateDirectoryCheckboxEnabled(false) + , m_Preferences(CPreferences::GetUserPreferences()) +{ + m_IsSaving = !bOpenFileDialog; // if not openfiledlg, is saving + m_FilterIndex = 0; // init to 0; index starts from 1 + m_ofnEx.pvReserved = nullptr; + m_ofnEx.dwReserved = 0; + m_ofnEx.FlagsEx = 0; + + if (dwFlags & OFN_ALLOWMULTISELECT) { + // Create buffer for multiple selection + m_FileListBuffer = new TCHAR[SFILELISTBUFFERSIZE]; + m_FileListBuffer[0] = '\0'; + + GetOFN().lpstrFile = m_FileListBuffer; + GetOFN().nMaxFile = SFILELISTBUFFERSIZE; + } +} + +CFileDialogEx::~CFileDialogEx() +{ + if (m_FileListBuffer) { + delete[] m_FileListBuffer; + } +} + +BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog) +//{{AFX_MSG_MAP(CFileDialogEX) +ON_COMMAND(IDC_CHECK1, OnCreateNewDirectory) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +/** + * IsWin2000: function to determine if we are on win2k + * + * @return true if we are on win2k + */ +//============================================================================== +// BOOL IsWin2000 () +//{ +// OSVERSIONINFOEX theOsvi; +// BOOL OsVersionInfoEx; +// +// // Try calling GetVersionEx using the OSVERSIONINFOEX structure, +// // which is supported on Windows 2000. +// // +// // If that fails, try using the OSVERSIONINFO structure. +// +// ZeroMemory( &theOsvi, sizeof( OSVERSIONINFOEX ) ); +// theOsvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX ); +// OsVersionInfoEx = GetVersionEx ( ( OSVERSIONINFO* ) &theOsvi ); +// +// if( !OsVersionInfoEx ) +// { +// // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. +// +// theOsvi.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ); +// if ( !GetVersionEx( ( OSVERSIONINFO* ) &theOsvi) ) +// return FALSE; +// } +// +// switch ( theOsvi.dwPlatformId ) +// { +// case VER_PLATFORM_WIN32_NT: +// +// if ( theOsvi.dwMajorVersion >= 5 ) +// return TRUE; +// +// break; +// } +// return FALSE; +//} + +void CFileDialogEx::EnableCreateDirectoryCheckbox() +{ + m_CreateDirectoryCheckboxEnabled = true; +} + +// http://msdn.microsoft.com/en-us/magazine/cc300434.aspx +struct RegKeyOverrider +{ + const char *getRegKeyName() + { + return "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\ComDlg32\\PlacesBar"; + } + HKEY m_TempKey; + + RegKeyOverrider() + { + memset(&m_TempKey, 0, sizeof(HKEY)); + long newKeyResult = + RegCreateKeyEx(HKEY_CURRENT_USER, L"UIComposer_FileDialog", 0, nullptr, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &m_TempKey, nullptr); + if (newKeyResult == ERROR_SUCCESS) { + long overrideResult = RegOverridePredefKey(HKEY_CURRENT_USER, m_TempKey); + ASSERT(overrideResult == ERROR_SUCCESS); + if (overrideResult == ERROR_SUCCESS) { + // Customize the places bar now in or overridden key. + HKEY placesKey; + long placesResult = + RegCreateKeyEx(HKEY_CURRENT_USER, CString(getRegKeyName()), 0, nullptr, + REG_OPTION_VOLATILE, KEY_ALL_ACCESS, nullptr, &placesKey, nullptr); + if (placesResult == ERROR_SUCCESS) { + TCHAR szHomeDirBuf[MAX_PATH] = { 0 }; + + HANDLE hToken = 0; + OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken); + + DWORD BufSize = MAX_PATH; + GetUserProfileDirectory(hToken, szHomeDirBuf, &BufSize); + + CloseHandle(hToken); + + wcscat(szHomeDirBuf, L"\\Links"); + + size_t len = wcslen(szHomeDirBuf); + RegSetValueEx(placesKey, L"Place0", 0, REG_SZ, (const BYTE *)szHomeDirBuf, + (DWORD)len); + + TCHAR buffer[32] = { 0 }; + DWORD folderIds[] = { 8, 0, 17, 18 }; + + for (int idx = 0; idx < 4; ++idx) { + swprintf_s(buffer, L"Place%d", idx + 1); + long setKeyResult = + RegSetValueEx(placesKey, buffer, 0, REG_DWORD, + (const BYTE *)(folderIds + idx), sizeof(DWORD)); + ASSERT(setKeyResult == ERROR_SUCCESS); + } + } + RegCloseKey(placesKey); + } + } + } + ~RegKeyOverrider() + { + RegOverridePredefKey(HKEY_CURRENT_USER, nullptr); + RegDeleteKey(m_TempKey, nullptr); + RegCloseKey(m_TempKey); + } +}; +struct SErrorMap +{ + DWORD m_Error; + const char *m_Name; +}; +static SErrorMap g_ErrorMap[] = { +#define MAKE_STRUCT(name) { name, #name }, + MAKE_STRUCT(CDERR_DIALOGFAILURE) MAKE_STRUCT(CDERR_FINDRESFAILURE) + MAKE_STRUCT(CDERR_INITIALIZATION) MAKE_STRUCT(CDERR_LOADRESFAILURE) + MAKE_STRUCT(CDERR_LOADSTRFAILURE) MAKE_STRUCT(CDERR_LOCKRESFAILURE) + MAKE_STRUCT(CDERR_MEMALLOCFAILURE) MAKE_STRUCT(CDERR_MEMLOCKFAILURE) + MAKE_STRUCT(CDERR_NOHINSTANCE) MAKE_STRUCT(CDERR_NOHOOK) + MAKE_STRUCT(CDERR_NOTEMPLATE) MAKE_STRUCT(CDERR_STRUCTSIZE) + MAKE_STRUCT(FNERR_BUFFERTOOSMALL) MAKE_STRUCT(FNERR_INVALIDFILENAME) + MAKE_STRUCT(FNERR_SUBCLASSFAILURE) +#undef MAKE_STRUCT + { 0, nullptr }, +}; +//============================================================================== +/** + * IsWin2000: Overloaded CFileDialog Function + * + * adds extra parameter if the operating system is win2k + * + * @return true for file open... false for file save as + */ +//============================================================================== +INT_PTR CFileDialogEx::DoModal() +{ + ASSERT_VALID(this); + ASSERT(m_ofn.Flags & OFN_ENABLEHOOK); + ASSERT(m_ofn.lpfnHook != nullptr); // can still be a user hook + + // zero out the file buffer for consistent parsing later + ASSERT(AfxIsValidAddress(m_ofn.lpstrFile, m_ofn.nMaxFile)); + DWORD nOffset = (DWORD)_tcslen(m_ofn.lpstrFile) + 1; + ASSERT(nOffset <= m_ofn.nMaxFile); + memset(m_ofn.lpstrFile + nOffset, 0, (m_ofn.nMaxFile - nOffset) * sizeof(TCHAR)); + + if (!m_InitialDir.IsEmpty()) + m_ofn.lpstrInitialDir = m_InitialDir; + + // If the title has been specified, change it from the OS default + if (!m_Title.IsEmpty()) + m_ofn.lpstrTitle = m_Title; + + // If filterIndex has been changed, use it instead of the default + if (m_FilterIndex != 0) + m_ofn.nFilterIndex = m_FilterIndex; + + if (m_CreateDirectoryCheckboxEnabled) { + // Begin customization for the checkbox for new project dialog + m_ofn.hInstance = GetModuleHandle(nullptr); + m_ofn.lpTemplateName = MAKEINTRESOURCE(IDD_NEWPROJEXT); + m_ofn.Flags |= OFN_ENABLETEMPLATE; + } + + // WINBUG: This is a special case for the file open/save dialog, + // which sometimes pumps while it is coming up but before it has + // disabled the main window. + HWND hWndFocus = ::GetFocus(); + BOOL bEnableParent = FALSE; + + // OVerride the places bar so that is always shows favorites. + RegKeyOverrider regOverrider; + m_ofn.hwndOwner = PreModal(); + AfxUnhookWindowCreate(); + if (m_ofn.hwndOwner != nullptr && ::IsWindowEnabled(m_ofn.hwndOwner)) { + bEnableParent = TRUE; + ::EnableWindow(m_ofn.hwndOwner, FALSE); + } + + _AFX_THREAD_STATE *pThreadState = AfxGetThreadState(); + ASSERT(pThreadState->m_pAlternateWndInit == nullptr); + + if (m_ofn.Flags & OFN_EXPLORER) + pThreadState->m_pAlternateWndInit = this; + else + AfxHookWindowCreate(this); + + // This is whre is differs for 2000 + ::memset(&m_ofnEx, 0, sizeof(m_ofnEx)); + ::memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn)); + // if ( IsWin2000() ){ + // m_ofnEx.lStructSize = sizeof( m_ofnEx ); + //} + + int nResult; + if (m_bOpenFileDialog) + nResult = ::GetOpenFileName(&m_ofnEx); + else + nResult = ::GetSaveFileName(&m_ofnEx); + + if (nResult == 0) { + DWORD error = ::CommDlgExtendedError(); + if (error) { + SErrorMap *theError = nullptr; + for (theError = g_ErrorMap; theError->m_Name; ++theError) { + if (theError->m_Error == error) { + OutputDebugStringA("Massive failure in FileDialogEX!!\n"); + OutputDebugStringA(theError->m_Name); + ASSERT(false); + } + } + } + } + + // Copy back m_ofnEx -> m_ofn + ::memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn)); + m_ofn.lStructSize = sizeof(m_ofn); + + if (nResult) + ASSERT(pThreadState->m_pAlternateWndInit == nullptr); + pThreadState->m_pAlternateWndInit = nullptr; + + // WINBUG: Second part of special case for file open/save dialog. + if (bEnableParent) + ::EnableWindow(m_ofn.hwndOwner, TRUE); + if (::IsWindow(hWndFocus)) + ::SetFocus(hWndFocus); + + PostModal(); + + if (nResult) { + m_LastFilterIndex = GetOFN().nFilterIndex; + } + + return nResult ? nResult : IDCANCEL; +} + +BOOL CFileDialogEx::OnFileNameOK() +{ + CFileStatus theFileStatus; + CString theFilePath = Q3DStudio::CString(GetOFN().lpstrFile); + // CString theFilePath = this->GetPathName(); // Somehow, this does not return the filename + // with extension + BOOL theReturnValue = FALSE; + + if (m_IsSaving && CFile::GetStatus(theFilePath, theFileStatus)) { + if (theFileStatus.m_attribute & CFile::readOnly) { + Q3DStudio::CString theMsgTitle; + Q3DStudio::CString theMsg; + Q3DStudio::CString theFormattedText; + Q3DStudio::CString theFileNameText = GetOFN().lpstrFileTitle; + // Q3DStudio::CString theFileNameText = GetFileName( ); + + theMsgTitle = ::LoadResourceString(IDS_PROJNAME); + theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING); + theFormattedText.Format(theMsg, static_cast<const wchar_t *>(theFileNameText)); + + ::MessageBox(this->GetSafeHwnd(), theFormattedText, theMsgTitle, + MB_OK | MB_ICONEXCLAMATION); + theReturnValue = TRUE; + } + } + + return theReturnValue; +} + +void CFileDialogEx::SetInitialDirectory(const Q3DStudio::CString &inDir) +{ + Q3DStudio::CFilePath thePath(inDir); + if (thePath.IsFile()) + thePath = thePath.GetDirectory(); + m_InitialDir = thePath; +} + +void CFileDialogEx::OnCreateNewDirectory() +{ + m_WasCreateNewDirectoryChecked = !m_WasCreateNewDirectoryChecked; + m_Preferences.SetValue("CreateDirForProject", m_WasCreateNewDirectoryChecked); +} + +//============================================================================= +/** + * Allows the user to set the title of the dialog. By default, the title is + * determined by the first parameter of the constructor (bOpenFileDialog). + * TRUE specifies a file open dialog and FALSE specifies a Save As dialog. + * The title of the window is then generated by the OS. This function enables + * you to set the title to any string you want, overriding the OS value. + * @param inTitle new title for this dialog; if an empty string is specified, + * the OS generated title will be displayed. + */ +void CFileDialogEx::SetWindowTitle(const Q3DStudio::CString &inTitle) +{ + m_Title = inTitle; +} + +//============================================================================= +/** + * Sets the filter to be selected when the dialog is opened, if specified. + * The filter is indexed from 1 to n. + * + * @param inFilterIndex the index of the filter to be applied as the default + * extension to be used when displaying the dialog. + * @author AT May 29 2003 + */ +void CFileDialogEx::SetFilterIndex(const LONG inFilterIndex) +{ + m_FilterIndex = inFilterIndex; +} + +BOOL CFileDialogEx::OnInitDialog() +{ + BOOL retval = CFileDialog::OnInitDialog(); + if (m_CreateDirectoryCheckboxEnabled) { + CWnd *theWnd = GetDlgItem(IDC_CHECK1); + if (theWnd) { + m_WasCreateNewDirectoryChecked = + m_Preferences.GetValue("CreateDirForProject", true) ? 1 : 0; + Button_SetCheck(theWnd->GetSafeHwnd(), m_WasCreateNewDirectoryChecked ? 1 : 0); + } + } + return retval; +} + +//============================================================================= +/** + * Gets the filter index when the dialog is opened. + * The filter is indexed from 1 to n. + * The member was set at the end of DoModal. + * + * @return the filter index, starting from 1 to n + */ +long CFileDialogEx::GetLastFilterIndex() +{ + return m_LastFilterIndex; +} + +//============================================================================= +/** + * Retrieves the list of files selected during multiple selection + * @param outFileList vector to hold filenames + */ +void CFileDialogEx::RetrieveFileList(TFILELIST &outFileList) const +{ + outFileList.clear(); + POSITION theStartPosition = GetStartPosition(); + + Q3DStudio::CString theFileName; + while (nullptr != theStartPosition) { + theFileName = GetNextPathName(theStartPosition); + outFileList.push_back(CUICFile(theFileName)); + } +} diff --git a/src/Authoring/Studio/_Win/UI/FileDialogEX.h b/src/Authoring/Studio/_Win/UI/FileDialogEX.h new file mode 100644 index 00000000..ad82de14 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/FileDialogEX.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#if !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_) +#define AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +struct OPENFILENAMEEX : public OPENFILENAME +{ + void *pvReserved; + DWORD dwReserved; + DWORD FlagsEx; +}; + +//============================================================================== +/** + * CFileDialog: Extends the regular CFileDialog for win2k dialog box + */ +//============================================================================== +class CFileDialogEx : public CFileDialog +{ + DECLARE_DYNAMIC(CFileDialogEx) + +public: + typedef std::vector<CUICFile> TFILELIST; + OPENFILENAMEEX m_ofnEx; ///< Extra structure passed in for win 2k dialog + + //========================================================================== + // Methods + //========================================================================== + CFileDialogEx(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = nullptr, LPCTSTR lpszFileName = nullptr, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, LPCTSTR lpszFilter = nullptr, + CWnd *pParentWnd = nullptr); + + virtual ~CFileDialogEx(); + + void EnableCreateDirectoryCheckbox(); + virtual void SetInitialDirectory(const Q3DStudio::CString &inDir); + virtual void SetWindowTitle(const Q3DStudio::CString &inTitle); + virtual void SetFilterIndex(const LONG inFilterIndex); + virtual BOOL OnInitDialog(); + long GetLastFilterIndex(); + void RetrieveFileList(TFILELIST &outFileList) const; + + virtual INT_PTR DoModal(); + virtual BOOL OnFileNameOK(); + void IsSaving() { m_IsSaving = TRUE; } + bool WasCreateNewDirectoryChecked() { return m_WasCreateNewDirectoryChecked; } + +protected: + BOOL m_IsSaving; + Q3DStudio::CString m_InitialDir; + Q3DStudio::CString m_Title; + LONG m_FilterIndex; + long m_LastFilterIndex; //< the last filter index for when a file was selected + wchar_t *m_FileListBuffer; + bool m_CreateDirectoryCheckboxEnabled; + bool m_WasCreateNewDirectoryChecked; + // We have to cache a CPreferences here because we reroute the registry during + // doModal in order to make the file dialogue behavior differently. + // see RegKeyOverrider + CPreferences m_Preferences; + + //========================================================================== + // Members + //========================================================================== + + // Generated message map functions + //{{AFX_MSG(CFileDialogEx) + afx_msg void OnCreateNewDirectory(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FILEDIALOGEX_H__4CF114A7_E3C1_44AA_8A73_92CF2480D010__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp new file mode 100644 index 00000000..cb02578b --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "stdafx.h" +#include "GLVersionDlg.h" + +CGLVersionDlg::CGLVersionDlg(CWnd *pParent /*=nullptr*/) + : CDialog(CGLVersionDlg::IDD, pParent) +{ + m_Title = _T(""); + m_Message = _T(""); + m_Icon = nullptr; + m_DontShowAgain = FALSE; +} + +CGLVersionDlg::~CGLVersionDlg() +{ +} + +void CGLVersionDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_GL_VERSION_ICON, m_WarningIcon); + DDX_Text(pDX, IDC_GL_VERSION_MESSAGE, m_Message); + DDX_Check(pDX, IDC_CHECK1, m_DontShowAgain); +} + +BEGIN_MESSAGE_MAP(CGLVersionDlg, CDialog) +END_MESSAGE_MAP() + +BOOL CGLVersionDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the title + this->SetWindowText(m_Title); + + // Set icon + m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(m_Icon)); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CGLVersionDlg::Initialize(const Q3DStudio::CString &inTitle, + const Q3DStudio::CString &inMessage, bool inErrorIcon) +{ + // Set title and message + m_Title = CString(inTitle); + m_Message = CString(inMessage); + + // Set which icon to load + if (inErrorIcon) + m_Icon = IDI_ERROR; + else + m_Icon = IDI_WARNING; +} + +BOOL CGLVersionDlg::GetDontShowAgain() +{ + return m_DontShowAgain; +} diff --git a/src/Authoring/Studio/_Win/UI/GLVersionDlg.h b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h new file mode 100644 index 00000000..908a8441 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/GLVersionDlg.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef INCLUDED_GL_VERSION_DLG +#define INCLUDED_GL_VERSION_DLG 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "resource.h" + +//============================================================================== +/** + * CGLVersionDlg: Dialog class for showing Open GL Version Warning + */ +//============================================================================== +class CGLVersionDlg : public CDialog +{ +public: + CGLVersionDlg(CWnd *pParent = nullptr); // standard constructor + virtual ~CGLVersionDlg(); + + // Dialog Data + enum { IDD = IDD_GL_VERSION_DLG }; + +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() + CStatic m_WarningIcon; // Warning icon + CString m_Title; // Title for the dialog + CString m_Message; // Warning message + BOOL m_DontShowAgain; // Set to true to "Don't show this dialog again" + LPCTSTR m_Icon; // Which icon to load + +public: + virtual BOOL OnInitDialog(); + void Initialize(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inMessage, + bool inErrorIcon); + BOOL GetDontShowAgain(); +}; + +#endif // INCLUDED_GL_VERSION_DLG diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp new file mode 100644 index 00000000..57d6ae1d --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix / Includes +//============================================================================== + +#include "stdafx.h" +#include "InterpolationDlg.h" +#include "ui_InterpolationDlg.h" + +//============================================================================== +/** + * Constructor: Creates a CInterpolationDlg. + * + * @param parent Pointer to the parent of this dialog (defaults to NULL) + */ +//============================================================================== +CInterpolationDlg::CInterpolationDlg(QWidget *parent) + : QDialog(parent) + , m_ui(new Ui::InterpolationDlg) +{ + m_ui->setupUi(this); +} + +CInterpolationDlg::~CInterpolationDlg() +{ + delete m_ui; + m_ui = nullptr; +} + +void CInterpolationDlg::setEaseIn(uint value) +{ + m_ui->easeInSlider->setValue(value); +} + +void CInterpolationDlg::setEaseOut(uint value) +{ + m_ui->easeOutSlider->setValue(value); +} + +int CInterpolationDlg::easeIn() const +{ + return m_ui->easeInSlider->value(); +} + +int CInterpolationDlg::easeOut() const +{ + return m_ui->easeOutSlider->value(); +} + + diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.h b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h new file mode 100644 index 00000000..5f371625 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef INCLUDED_INTERPOLATION_DLG +#define INCLUDED_INTERPOLATION_DLG 1 + +#pragma once + +#include <QDialog> + +namespace Ui { +class InterpolationDlg; +} + +//============================================================================== +/** + * CInterpolationDlg: Dialog class for editing the ease-in/ease-out values of keyframes. + */ +//============================================================================== +class CInterpolationDlg : public QDialog +{ + Q_OBJECT +public: + explicit CInterpolationDlg(QWidget *parent = nullptr); // standard constructor + ~CInterpolationDlg(); + + void setEaseIn(uint value); + void setEaseOut(uint value); + int easeIn() const; + int easeOut() const; + +protected: + Ui::InterpolationDlg* m_ui = nullptr; +}; + +#endif // INCLUDED_INTERPOLATION_DLG diff --git a/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui new file mode 100644 index 00000000..f0a0a759 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/InterpolationDlg.ui @@ -0,0 +1,305 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>InterpolationDlg</class> + <widget class="QDialog" name="InterpolationDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>425</width> + <height>195</height> + </rect> + </property> + <property name="windowTitle"> + <string>Set Keyframe Interpolation</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="1" colspan="2"> + <widget class="QSlider" name="easeOutSlider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Ease In:</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_4"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Smooth</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QSlider" name="easeInSlider"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximum"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="tickPosition"> + <enum>QSlider::TicksBelow</enum> + </property> + <property name="tickInterval"> + <number>10</number> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_3"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Linear</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_5"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Linear</string> + </property> + </widget> + </item> + <item row="3" column="2"> + <widget class="QLabel" name="label_6"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Maximum"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Smooth</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_2"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Ease Out:</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QSpinBox" name="easeInSpinBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QSpinBox" name="easeOutSpinBox"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + <property name="maximum"> + <number>100</number> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>InterpolationDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>224</x> + <y>272</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>InterpolationDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>easeInSlider</sender> + <signal>valueChanged(int)</signal> + <receiver>easeInSpinBox</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>331</x> + <y>21</y> + </hint> + <hint type="destinationlabel"> + <x>542</x> + <y>35</y> + </hint> + </hints> + </connection> + <connection> + <sender>easeOutSlider</sender> + <signal>valueChanged(int)</signal> + <receiver>easeOutSpinBox</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>210</x> + <y>93</y> + </hint> + <hint type="destinationlabel"> + <x>545</x> + <y>93</y> + </hint> + </hints> + </connection> + <connection> + <sender>easeInSpinBox</sender> + <signal>valueChanged(int)</signal> + <receiver>easeInSlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>533</x> + <y>24</y> + </hint> + <hint type="destinationlabel"> + <x>408</x> + <y>18</y> + </hint> + </hints> + </connection> + <connection> + <sender>easeOutSpinBox</sender> + <signal>valueChanged(int)</signal> + <receiver>easeOutSlider</receiver> + <slot>setValue(int)</slot> + <hints> + <hint type="sourcelabel"> + <x>546</x> + <y>98</y> + </hint> + <hint type="destinationlabel"> + <x>338</x> + <y>84</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.cpp b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp new file mode 100644 index 00000000..a253e89a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MemoryDC.cpp @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "resource.h" +#include "MemoryDC.h" + +///////////////////////////////////////////////////////////////////////////// +// CMemoryDC + +//============================================================================== +/* + * Constructor: Initializes the object. + */ +//============================================================================== +CMemoryDC::CMemoryDC() + : m_ValidFlag(FALSE) + , m_SrcDC(nullptr) + , m_OldBmp(nullptr) +{ +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CMemoryDC::~CMemoryDC() +{ + // automatically release and draw on exit + Release(); +} + +//============================================================================== +/** + * Create + * + * Creates the memory DC and image bitmap + * + * @param inDC Source device context + * @param inSrcRect CRect containing the source rectangle for drawing + */ +//============================================================================== +void CMemoryDC::Create(CDC *inDC, CRect inSrcRect) +{ + ASSERT(inDC != nullptr); + + if (!m_ValidFlag) { + // create the memory DC + CreateCompatibleDC(inDC); + + // save the source DC + m_SrcDC = inDC; + + // keep track of the destination rectangle + m_SrcRect.CopyRect(inSrcRect); + + // create a bitmap for the memory bitmap image + m_MemBmp.CreateCompatibleBitmap(inDC, inSrcRect.Width(), inSrcRect.Height()); + + // select the memory image into the memory DC + m_OldBmp = SelectObject(&m_MemBmp); + + m_ValidFlag = TRUE; + } +} + +//============================================================================== +/** + * Release + * + * Releases the memory DC and image bitmap and optionally copies the image + * to the source DC. + * + * @param inCopyToSourceFlag If TRUE, copies the memory image to the source DC + */ +//============================================================================== +void CMemoryDC::Release(BOOL inCopyToSourceFlag) +{ + // copy the offscreen buffer to the sourceDC passed in Create() + + if (m_ValidFlag) { + // blit to source DC to the m_SrcRect + if ((inCopyToSourceFlag) && (m_SrcDC != nullptr)) + m_SrcDC->BitBlt(m_SrcRect.left, m_SrcRect.top, m_SrcRect.Width(), m_SrcRect.Height(), + this, 0, 0, SRCCOPY); + + // de-select the memory image from the DC + SelectObject(m_OldBmp); + + // delete the memory bitmap image + m_MemBmp.DeleteObject(); + + // delete the memory DC + DeleteDC(); + + m_ValidFlag = FALSE; + m_OldBmp = nullptr; + } +} + +//============================================================================== +/** + * CopySourceImage + * + * Copies the source image from the m_SrcRect into the memory DC/image. + * + * @param None + */ +//============================================================================== +void CMemoryDC::CopySourceImage() +{ + if (m_ValidFlag) { + // copy the image from the source rectangle to the offscreen image + if (m_SrcDC != nullptr) + this->BitBlt(0, 0, m_SrcRect.Width(), m_SrcRect.Height(), m_SrcDC, m_SrcRect.left, + m_SrcRect.top, SRCCOPY); + } +} + +//============================================================================== +/** + * ConvertRect + * + * Converts a rectangle based on the source coordinates to one based on + * the memory image's coordinates. + * + * @param inDrawRect Source drawing CRect + * + * @return CRect Contains the converted rectangle + */ +//============================================================================== +CRect CMemoryDC::ConvertRect(CRect inDrawRect) +{ + CRect theRect; + + theRect.CopyRect(inDrawRect); + theRect.OffsetRect(-m_SrcRect.left, -m_SrcRect.top); + + return theRect; +} + +//============================================================================== +/** + * ConvertPoint + * + * Converts a point based on the source coordinates to one based on + * the memory image's coordinates. + * + * @param inDrawRect Source drawing CPoint + * + * @return CPoint Contains the converted point + */ +//============================================================================== +CPoint CMemoryDC::ConvertPoint(CPoint inDrawPoint) +{ + CPoint thePoint; + + // convert point relative to this DC + thePoint = inDrawPoint; + thePoint.x -= m_SrcRect.left; + thePoint.y -= m_SrcRect.top; + + return thePoint; +} + +//============================================================================== +/** + * ConvertXPos + * + * Converts an x-position based on the source coordinates to one based on + * the memory image's coordinates. + * + * @param inXValue Source drawing x-position + * + * @return long Contains the converted x-position + */ +//============================================================================== +long CMemoryDC::ConvertXPos(long inXValue) +{ + long theXPos; + + // convert x coordinate relative to this DC + theXPos = (long)inXValue - (long)m_SrcRect.left; + + return theXPos; +} + +//============================================================================== +/** + * ConvertYPos + * + * Converts an y-position based on the source coordinates to one based on + * the memory image's coordinates. + * + * @param inYValue Source drawing y-position + * + * @return long Contains the converted y-position + */ +//============================================================================== +long CMemoryDC::ConvertYPos(long inYValue) +{ + long theYPos; + + // convert y coordinate relative to this DC + theYPos = (long)inYValue - (long)m_SrcRect.top; + + return theYPos; +} + +//============================================================================== +/** + * SetRect + * + * Sets the drawing/output bounding rectangle. + * + * @param inRect Bounding rectangle for drawing + */ +//============================================================================== +void CMemoryDC::SetRect(CRect inRect) +{ + m_SrcRect = inRect; +} diff --git a/src/Authoring/Studio/_Win/UI/MemoryDC.h b/src/Authoring/Studio/_Win/UI/MemoryDC.h new file mode 100644 index 00000000..f72701e0 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MemoryDC.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_MEMORY_DC_H +#define INCLUDED_MEMORY_DC_H + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +//============================================================================== +/** + * CMemoryDC: Subclassed CDC for drawing offscreen + * + * This is a subclassed CDC so we can control drawing into a DC with offscreen + * buffers to prevent flickering. + */ +//============================================================================== + +class CMemoryDC : public CDC +{ +public: + //========================================================================== + // Fields + //========================================================================== + +protected: + BOOL m_ValidFlag; // TRUE if we can successfully release/copy the offscreen image to the screen + CRect m_SrcRect; // Bounding rectangle for drawing + CBitmap m_MemBmp; // Offscreen bitmap image + CBitmap *m_OldBmp; // Previous bitmap in the offscreen DC + CDC *m_SrcDC; // Source device context for final blit + + //========================================================================== + // Methods + //========================================================================== + +public: + void SetRect(CRect inRect); + + // Construction + + CMemoryDC(); + virtual ~CMemoryDC(); + + // Access + + CPoint ConvertPoint(CPoint inDrawPoint); + CRect ConvertRect(CRect inDrawRect); + long ConvertXPos(long inXValue); + long ConvertYPos(long inYValue); + void CopySourceImage(); + void Create(CDC *inDC, CRect inSrcRect); + + void Release(BOOL inCopyToSourceFlag = TRUE); +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // INCLUDED_MEMORY_DC_H diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.cpp b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp new file mode 100644 index 00000000..39c82246 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MenuEdit.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== + +#include "stdafx.h" +#include "MenuEdit.h" +#include "BCMenu.h" +#include "StudioColors.h" + +//============================================================================== +// Message Map +//============================================================================== + +BEGIN_MESSAGE_MAP(CMenuEdit, CEdit) +//{{AFX_MSG_MAP(CMenuEdit) +ON_WM_SETFOCUS() +ON_WM_CONTEXTMENU() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +// IMPLEMENTATION +//============================================================================== + +//============================================================================== +/** + * Constructor: Creates a CMenuEdit + */ +//============================================================================== +CMenuEdit::CMenuEdit() +{ +} + +//============================================================================== +/** + * OnSetFocus: The message handler for accepting focus. + * + * @param pOldWnd The window that had focus last. + */ +//============================================================================== +void CMenuEdit::OnSetFocus(CWnd *pOldWnd) +{ + // Allow the parent to handle the request. + CEdit::OnSetFocus(pOldWnd); + + // Select the entire text. + this->SetSel(0, -1); +} + +//****************************************************************************** +// DYNAMIC CREATION +//****************************************************************************** + +IMPLEMENT_DYNAMIC(CMenuEdit, CEdit) + +//============================================================================== +/** + * OnContextMenu: WM_CONTEXTMENU handler for the CMenuEdit. + * + * @param inWnd This window. + * @param inPoint Mouse position when the right button was clicked. + */ +//============================================================================== +void CMenuEdit::OnContextMenu(CWnd *inWnd, CPoint inPoint) +{ + Q_UNUSED(inWnd); + + // Added just because Justin has an eye for detail. :) + + BCMenu theMenu; + BCMenu *thePopupMenu = nullptr; + long theMenuCmd; + + if (GetFocus() != this) + this->SetFocus(); + + // Load the context menu + theMenu.LoadMenu(IDR_CONTEXT_EDIT); +#ifdef _USECONTENTMENUIMAGES_ + theMenu.SetBitmapBackground(MENU_IMAGELIST_BACKCOLOR); + theMenu.LoadToolbar(IDC_EDITCONTEXTTOOLBAR); +#endif + + thePopupMenu = (BCMenu *)theMenu.GetSubMenu(0); + + // Enable/disable menu items + if (!this->CanUndo()) + thePopupMenu->EnableMenuItem(IDC_UNDO, MF_BYCOMMAND | MF_GRAYED); + + // Disable the Select All if there is no text in the control + if (this->GetWindowTextLength() == 0) + thePopupMenu->EnableMenuItem(IDC_SELECTALL, MF_BYCOMMAND | MF_GRAYED); + + // Disable paste if there is no CF_TEXT on the clipboard + if (!IsClipboardFormatAvailable(CF_TEXT)) + thePopupMenu->EnableMenuItem(IDC_PASTE, MF_BYCOMMAND | MF_GRAYED); + + // Check if any text is selected + DWORD theSelection = this->GetSel(); + if (LOWORD(theSelection) == HIWORD(theSelection)) { + // Disable cut, copy and delete commands if no text is selected + thePopupMenu->EnableMenuItem(IDC_CUT, MF_BYCOMMAND | MF_GRAYED); + thePopupMenu->EnableMenuItem(IDC_COPY, MF_BYCOMMAND | MF_GRAYED); + thePopupMenu->EnableMenuItem(IDC_DELETE, MF_BYCOMMAND | MF_GRAYED); + } + + // Post the menu and handle the command here. + theMenuCmd = (long)thePopupMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD + | TPM_NONOTIFY, + inPoint.x, inPoint.y, this, nullptr); + switch (theMenuCmd) { + case IDC_UNDO: + this->Undo(); + break; + + case IDC_CUT: + this->Cut(); + break; + + case IDC_COPY: + this->Copy(); + break; + + case IDC_PASTE: + this->Paste(); + break; + + case IDC_DELETE: + // Delete the selected text + this->ReplaceSel(L"", FALSE); + break; + + case IDC_SELECTALL: + // Select the entire text. + this->SetSel(0, -1); + break; + } + + theMenu.DestroyMenu(); +} diff --git a/src/Authoring/Studio/_Win/UI/MenuEdit.h b/src/Authoring/Studio/_Win/UI/MenuEdit.h new file mode 100644 index 00000000..9aae97e2 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MenuEdit.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef _MENUEDIT_H_ +#define _MENUEDIT_H_ + +//============================================================================== +// Forwards +//============================================================================== + +//============================================================================== +// Class +//============================================================================== + +//============================================================================== +/** + * @class CMenuEdit + * @brief This edit control has a BCMenu context menu. + */ +//============================================================================== +class CMenuEdit : public CEdit +{ + // Fields + +public: + // Methods + +public: + DECLARE_DYNAMIC(CMenuEdit) + CMenuEdit(); + virtual ~CMenuEdit() {} + +protected: + //{{AFX_MSG(CMenuEdit) + afx_msg void OnSetFocus(CWnd *pOldWnd); + afx_msg void OnContextMenu(CWnd *pWnd, CPoint point); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +#endif // _MENUEDIT_H_ diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.cpp b/src/Authoring/Studio/_Win/UI/MenuItem.cpp new file mode 100644 index 00000000..beb77d98 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MenuItem.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "stdafx.h" +#include "MenuItem.h" + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +//============================================================================== +/** + * CMenuItem: constructor + * + * @param inName name of the file + * @param inPath path to the file + * @param inID ID tag for this handler in the menu + */ +//============================================================================== +CMenuItem::CMenuItem(CString inName, CString inPath, UINT inID) +{ + m_Name = inName; + m_ID = inID; + m_Path = inPath; +} + +CMenuItem::~CMenuItem() +{ +} diff --git a/src/Authoring/Studio/_Win/UI/MenuItem.h b/src/Authoring/Studio/_Win/UI/MenuItem.h new file mode 100644 index 00000000..f8033b81 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/MenuItem.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_) +#define AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//============================================================================== +// CMenuItem Class +//============================================================================== + +//============================================================================== +/** + * CMenuItem: Object for creating dynamic menus + */ +//============================================================================== +class CMenuItem : public CObject +{ +public: + CMenuItem(CString inName, CString inPath, UINT inID); + virtual ~CMenuItem(); + UINT GetID() { return m_ID; }; + CString GetPath() { return m_Path; }; + CString GetName() { return m_Name; }; +protected: + CString m_Path; ///< Path to the file + CString m_Name; ///< Name to use in the menu + UINT m_ID; ///< ID of this menu item +}; + +#endif // !defined(AFX_MENUITEM_H__6383095D_C084_44EB_A6D0_04CC1DA1B74F__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.cpp b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp new file mode 100644 index 00000000..73ff7bc8 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/NumericEdit.cpp @@ -0,0 +1,347 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "NumericEdit.h" + +#include <minmax.h> + +///////////////////////////////////////////////////////////////////////////// +// CNumericEdit class + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CNumericEdit::CNumericEdit() +{ + m_RangeLow = -1; + m_RangeHigh = -1; + + m_WrapFlag = FALSE; +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CNumericEdit::~CNumericEdit() +{ +} + +//============================================================================= +/** + * Message Map + */ +//============================================================================= +BEGIN_MESSAGE_MAP(CNumericEdit, CEdit) +//{{AFX_MSG_MAP(CNumericEdit) +ON_CONTROL_REFLECT(EN_KILLFOCUS, OnKillFocus) +ON_CONTROL_REFLECT(EN_UPDATE, OnUpdate) +ON_WM_CHAR() +ON_WM_MOUSEWHEEL() +ON_WM_KEYDOWN() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================= +/** + * SetRange: Sets the value range for this control. + * + * @param inRangeLow Low range. + * @param inRangeHigh High range + */ +//============================================================================= +void CNumericEdit::SetRange(long inRangeLow, long inRangeHigh) +{ + // Ensure they are in low/high order + m_RangeLow = min(inRangeLow, inRangeHigh); + m_RangeHigh = max(inRangeLow, inRangeHigh); +} + +//============================================================================= +/** + * SetValue: Sets the numeric value for this control. + * + * @param inValue The new value for this control. + */ +//============================================================================= +void CNumericEdit::SetValue(long inValue) +{ + CString theStrValue; + + theStrValue.Format(L"%lu", inValue); + this->SetWindowText(theStrValue); +} + +//============================================================================= +/** + * GetValue: Returns the numeric value for this control. + * + * @param None + * + * @return long The numeric value for this control. + */ +//============================================================================= +long CNumericEdit::GetValue() +{ + CString theStrValue; + + // Get the current control value. + this->GetWindowText(theStrValue); + + // Convert to long and return. + return atol((char *)LPCTSTR(theStrValue)); +} + +///////////////////////////////////////////////////////////////////////////// +// CNumericEdit message handlers + +//============================================================================= +/** + * OnKillFocus: Handle the EN_KILLFOCUS and validate data. + * + * @param None + */ +//============================================================================= +void CNumericEdit::OnKillFocus() +{ + this->ValidateData(); +} + +//============================================================================= +/** + * OnUpdate: Handle the EN_UPDATE and handle validation before the control is updated. + * + * @param None + */ +//============================================================================= +void CNumericEdit::OnUpdate() +{ + // TODO: If this is a RICHEDIT control, the control will not + // send this notification unless you override the CEdit::OnInitDialog() + // function to send the EM_SETEVENTMASK message to the control + // with the ENM_UPDATE flag ORed into the lParam mask. + + // TODO: Add your control notification handler code here + + this->ValidateData(); +} + +//============================================================================= +/** + * OnChar: Handle the WM_CHAR and validate the key that was pressed. + * + * @param inChar + * @param inRepCnt + * @param inFlags + */ +//============================================================================= +void CNumericEdit::OnChar(UINT inChar, UINT inRepCnt, UINT inFlags) +{ + if (IsNumeric(inChar) || IsEditKey(inChar)) { + CEdit::OnChar(inChar, inRepCnt, inFlags); + } +} + +//============================================================================= +/** + * OnKeyDown: Handle the WM_KEYDOWN and validate the key that was pressed. + * + * @param inChar + * @param inRepCnt + * @param inFlags + */ +//============================================================================= +void CNumericEdit::OnKeyDown(UINT inChar, UINT inRepCnt, UINT inFlags) +{ + if (inChar == VK_UP) { + this->IncrementValue(+1); + this->SetSel(0, -1); + } else if (inChar == VK_DOWN) { + this->IncrementValue(-1); + this->SetSel(0, -1); + } else { + CEdit::OnKeyDown(inChar, inRepCnt, inFlags); + } +} + +//============================================================================= +/** + * IsEditKey: Determine if the pressed key was an edit key. + * + * @param inChar Key character value. + * + * @return TRUE if an editing key + */ +//============================================================================= +BOOL CNumericEdit::IsEditKey(UINT inChar) +{ + BOOL theEditKeyFlag = FALSE; + + if (inChar == VK_DELETE || inChar == VK_BACK || inChar == VK_LEFT || inChar == VK_RIGHT + || inChar == VK_HOME || inChar == VK_END || inChar == VK_UP || inChar == VK_DOWN) + theEditKeyFlag = TRUE; + + return theEditKeyFlag; +} + +//============================================================================= +/** + * IsNumeric: Determine if the pressed key was a numeric key. + * + * @param inChar Key character value. + * + * @return TRUE if a numeric key + */ +//============================================================================= +BOOL CNumericEdit::IsNumeric(UINT inChar) +{ + CString theNumericCheck = L"0123456789"; + BOOL theNumericFlag = FALSE; + + // Determine if the character is a numeric value. + if (theNumericCheck.Find((TCHAR)inChar) != -1) { + theNumericFlag = TRUE; + } + + return theNumericFlag; +} + +//============================================================================= +/** + * ValidateData: Validates the value in the control to keep within range. + * + * @param None + */ +//============================================================================= +void CNumericEdit::ValidateData() +{ + CString theStrValue; + long theValue = 0; + BOOL theChangeFlag = FALSE; + + // Get the current text in the control. + this->GetWindowText(theStrValue); + if (theStrValue.GetLength() == 0) { + theValue = 0; + theChangeFlag = TRUE; + } else + // Check to see that a range has been set + if (m_RangeLow != -1 && m_RangeHigh != -1) { + theValue = this->GetValue(); + + // Check against the low and high range + if (theValue < m_RangeLow) { + theValue = m_RangeLow; + theChangeFlag = TRUE; + } else if (theValue > m_RangeHigh) { + theValue = m_RangeHigh; + theChangeFlag = TRUE; + } + } + + // Has the value changed? + if (theChangeFlag) { + // Update the control's value. + this->SetValue(theValue); + this->SetSel(0, -1); + } +} + +//============================================================================= +/** + * IncrementValue: Increments the current value by inAmount + * + * @param inAmount Amount to change the current control value. + */ +//============================================================================= +void CNumericEdit::IncrementValue(long inAmount) +{ + long theValue; + + // Get the current value + theValue = this->GetValue(); + + // Change theValue + theValue += inAmount; + + // Has a range been set? + if (m_RangeLow != -1 && m_RangeHigh != -1) { + if (theValue < m_RangeLow) { + theValue = m_RangeLow; + + if (m_WrapFlag) + theValue = m_RangeHigh; + } else if (theValue > m_RangeHigh) { + theValue = m_RangeHigh; + + if (m_WrapFlag) + theValue = m_RangeLow; + } + } + + this->SetValue(theValue); +} + +//============================================================================= +/** + * OnMouseWheel: Handle the WM_MOUSEWHEEL message. + * + * @param inFlags + * @param inzDelta + * @param inPoint + * + * @return TRUE if processed. + */ +//============================================================================= +BOOL CNumericEdit::OnMouseWheel(UINT inFlags, short inzDelta, CPoint inPoint) +{ + long theWheelDelta = 0; + + if (inzDelta != 0) + theWheelDelta = inzDelta / abs(inzDelta); + + this->IncrementValue(theWheelDelta); + + this->SetSel(0, -1); + + return CEdit::OnMouseWheel(inFlags, inzDelta, inPoint); +} diff --git a/src/Authoring/Studio/_Win/UI/NumericEdit.h b/src/Authoring/Studio/_Win/UI/NumericEdit.h new file mode 100644 index 00000000..61a4017a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/NumericEdit.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_) +#define AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//============================================================================== +// Includes +//============================================================================== + +#include "MenuEdit.h" + +///////////////////////////////////////////////////////////////////////////// +// CNumericEdit window + +class CNumericEdit : public CMenuEdit +{ + // Construction +public: + CNumericEdit(); + + // Attributes +public: + void SetAllowWrap(BOOL inWrapFlag) { m_WrapFlag = inWrapFlag; } + +protected: + long m_RangeLow, m_RangeHigh; + BOOL m_WrapFlag; + + // Operations +public: + long GetValue(); + + void SetRange(long inRangeLow, long inRangeHigh); + void SetValue(long inValue); + +protected: + void IncrementValue(long inAmount); + BOOL IsEditKey(UINT inChar); + BOOL IsNumeric(UINT inChar); + + void ValidateData(); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNumericEdit) + //}}AFX_VIRTUAL + + // Implementation +public: + virtual ~CNumericEdit(); + + // Generated message map functions +protected: + //{{AFX_MSG(CNumericEdit) + afx_msg void OnKillFocus(); + afx_msg void OnUpdate(); + afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_NUMERICEDIT_H__F08CC602_8CD7_4A27_AC46_48A80A7D8FD0__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp new file mode 100644 index 00000000..64d7e2f0 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.cpp @@ -0,0 +1,510 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#include "UICOptions.h" +#include "SceneView.h" +#include "Doc.h" +#include "StudioProjectSettings.h" +#include "Dispatch.h" +#include "HotKeys.h" +#include "MasterP.h" +#include "StudioApp.h" +#include "IStudioRenderer.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "PlatformStrings.h" +#include "PlayerContainerWnd.h" +#include "UICDMStudioSystem.h" +#include "Core.h" +#include "MainFrm.h" +#include "StudioUtils.h" + +#include <QtWidgets/qscrollbar.h> +#include <QtGui/qevent.h> + +//============================================================================== +// Class CPlayerContainerWnd +//============================================================================== + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CPlayerContainerWnd::CPlayerContainerWnd(CSceneView *inSceneView) + : QAbstractScrollArea(inSceneView) + , m_SceneView(inSceneView) + , m_PlayerWnd(NULL) + , m_IsMouseDown(false) + , m_IsMiddleMouseDown(false) + , m_ViewMode(VIEW_SCENE) +{ + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CPlayerContainerWnd::~CPlayerContainerWnd() +{ +} + +bool CPlayerContainerWnd::ShouldHideScrollBars() +{ + return m_ViewMode == VIEW_EDIT || g_StudioApp.IsAuthorZoom(); +} + +//============================================================================== +/** + * SetPlayerWndPosition: Sets the position of the child player window + * + * Called when the view is scrolled to position the child player window + * @param outLeftPresentationEdge the left edge of the presentation, with the scroll position + *taken into consideration + * @param outTopPresentionEdge the top edge of the presentation, with the scroll + *position taken into consideration + * + */ +//============================================================================== +void CPlayerContainerWnd::SetPlayerWndPosition(long &outLeftPresentationEdge, + long &outTopPresentionEdge) +{ + long theHScrollPosition, theVScrollPosition; + // Negate to adjust actual client positions + theHScrollPosition = -horizontalScrollBar()->value(); + theVScrollPosition = -verticalScrollBar()->value(); + + QRect theClientRect = rect(); + + // Horizontal scrollbar does not exist + if (m_ClientRect.width() < theClientRect.width()) { + theHScrollPosition = + theClientRect.left() + (theClientRect.width() / 2) - (m_ClientRect.width() / 2); + outLeftPresentationEdge = theHScrollPosition; + } else // This stays a negated value + outLeftPresentationEdge = theHScrollPosition; + + // Vertical scrollbar does not exist + if (m_ClientRect.height() < theClientRect.height()) { + theVScrollPosition = + theClientRect.top() + (theClientRect.height() / 2) - (m_ClientRect.height() / 2); + outTopPresentionEdge = theVScrollPosition; + } else // This stays a negated value + outTopPresentionEdge = theVScrollPosition; + + // Move the child player window + m_PlayerWnd->setGeometry(QRect(QPoint(theHScrollPosition, theVScrollPosition), m_ClientRect.size())); +} + +//============================================================================== +/** + * SetScrollRanges: Sets the scroll ranges when the view is being resized + */ +//============================================================================== +void CPlayerContainerWnd::SetScrollRanges() +{ + + long theScrollWidth = 0; + long theScrollHeight = 0; + +#ifdef INCLUDE_EDIT_CAMERA + if (ShouldHideScrollBars()) { + horizontalScrollBar()->setRange(0, 0); + verticalScrollBar()->setRange(0, 0); + horizontalScrollBar()->setValue(0); + verticalScrollBar()->setValue(0); + } else +#endif + { + QSize theSize = GetEffectivePresentationSize(); + + theScrollWidth = theSize.width(); + theScrollHeight = theSize.height(); + + + // Set scrollbar ranges + horizontalScrollBar()->setRange(0, theScrollWidth - width()); + verticalScrollBar()->setRange(0, theScrollHeight - height()); + horizontalScrollBar()->setPageStep(width()); + verticalScrollBar()->setPageStep(height()); + horizontalScrollBar()->setVisible(true); + verticalScrollBar()->setVisible(true); + } +} + +//============================================================================== +/** + * OnRulerGuideToggled: + * Handle scrollbar position when ruler, guide has been toggled + * + */ +//============================================================================== +void CPlayerContainerWnd::OnRulerGuideToggled() +{ + int scrollAmount = g_StudioApp.GetRenderer().AreGuidesEnabled() ? 16 : -16; + bool hasHorz = horizontalScrollBar()->isVisible(); + bool hasVert = verticalScrollBar()->isVisible(); + int hscrollPos = 0, vscrollPos = 0; + if (hasHorz) { + hscrollPos = qMax(horizontalScrollBar()->value() + scrollAmount, 0); + } + if (hasVert) { + vscrollPos = qMax(verticalScrollBar()->value() + scrollAmount, 0); + } + horizontalScrollBar()->setValue(hscrollPos); + verticalScrollBar()->setValue(vscrollPos); + m_PlayerWnd->update(); +} + +//============================================================================== +/** + * RecenterClient: Recenters the Client rect in the View's client area. + */ +//============================================================================== +void CPlayerContainerWnd::RecenterClient() +{ + QRect theViewClientRect = rect(); + QSize theClientSize; + m_ClientRect = theViewClientRect; + +#ifdef INCLUDE_EDIT_CAMERA + if (ShouldHideScrollBars()) { + } else +#endif + { + theClientSize = GetEffectivePresentationSize(); + + // Only center if we need to scroll + if (theClientSize.width() > theViewClientRect.width()) { + // compute the size of the client rectangle to display + m_ClientRect.setLeft( + (theViewClientRect.width() / 2) - (theClientSize.width() / 2) - (theClientSize.width() % 2)); + m_ClientRect.setRight((theViewClientRect.width() / 2) + (theClientSize.width() / 2)); + } + + if (theClientSize.height() > theViewClientRect.height()) { + m_ClientRect.setTop( + (theViewClientRect.height() / 2) - (theClientSize.height() / 2) - (theClientSize.height() % 2)); + m_ClientRect.setBottom((theViewClientRect.height() / 2) + (theClientSize.height() / 2)); + } + } + + QRect glRect = m_ClientRect; + glRect.setWidth(int(devicePixelRatio() * m_ClientRect.width())); + glRect.setHeight(int(devicePixelRatio() * m_ClientRect.height())); + g_StudioApp.GetRenderer().SetViewRect(glRect); +} + +//============================================================================== +/** + * OnLButtonDown: Called whenever the user left clicks in the view. + * This processes the WM_LBUTTONDOWN message. This message is generated whenever + * the user left clicks in the view. Since this could involve selection of an item + * in the scene, it may (if the click is in the Client rect) call ProcessMouseClick() + * on the Document to perform the selection. + * @param inFlags the flags passed in from the message call + * @param inPoint the point where the event takes place + */ +void CPlayerContainerWnd::mousePressEvent(QMouseEvent *event) +{ + if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) { + long theToolMode = g_StudioApp.GetToolMode(); + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte, event->pos(), + theToolMode); + m_IsMouseDown = true; + } else if (event->button() == Qt::MiddleButton) { +#ifdef INCLUDE_EDIT_CAMERA + const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier; + const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier; + + bool theToolChanged = false; + if (rect().contains(event->pos()) && !IsDeploymentView()) { + // If both the control key and the Alt key is not down + if (!theCtrlKeyIsDown && !theAltKeyIsDown) { + // press Scroll Wheel Click + // Do Camera Pan + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + theToolChanged = true; + } else if ((theAltKeyIsDown) && (!theCtrlKeyIsDown)) { + // press Alt-Scroll Wheel Click + // Do Camera Rotate if we are in 3D Camera + if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation( + g_StudioApp.GetRenderer().GetEditCamera())) { + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE); + theToolChanged = true; + } + } + } + + if (theToolChanged) { + Q_EMIT toolChanged(); + m_SceneView->SetViewCursor(); + + long theToolMode = g_StudioApp.GetToolMode(); + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::Matte, + event->pos(), theToolMode); + m_IsMouseDown = true; + m_IsMiddleMouseDown = true; + } +#else + Q_UNUSED(inFlags); + Q_UNUSED(inPoint); +#endif + } +} + +//============================================================================== +/** + * OnLButtonUp: Called whenever the user releases the left mouse button. + * + * This processes the WM_LBUTTONUP message. This message is generated whenever + * the left mouse button. We release the mouse capture to stop dragging. + * + * @param inFlags The flags passed in from the message call + * @param inPoint The point where the event takes place + */ +//============================================================================== +void CPlayerContainerWnd::mouseReleaseEvent(QMouseEvent *event) +{ + if ((event->button() == Qt::LeftButton) || (event->button() == Qt::RightButton)) { + // Need to commit the current command when we have a mouse up. :) + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte); + g_StudioApp.GetCore()->CommitCurrentCommand(); + m_IsMouseDown = false; + } else if (event->button() == Qt::MiddleButton) { + #ifdef INCLUDE_EDIT_CAMERA + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::Matte); + g_StudioApp.GetCore()->CommitCurrentCommand(); + if (m_IsMiddleMouseDown) { + m_IsMouseDown = false; + m_IsMiddleMouseDown = false; + + const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier; + const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier; + + if (!IsDeploymentView()) { + if (!theCtrlKeyIsDown && !theAltKeyIsDown) { + // none of the modifier key is pressed... reset to previous tool + m_SceneView->RestorePreviousTool(); + } else if (theCtrlKeyIsDown && theAltKeyIsDown) { + // since both modifier is down... let the ctrl has priority + m_SceneView->SetToolOnCtrl(); + } + m_SceneView->SetViewCursor(); + Q_EMIT toolChanged(); + } + } + #endif + } +} + +//============================================================================== +/** + * OnMouseMove: Called whenever the user moves the mouse in the window. + * + * This processes the WM_MOUSEMOVE message. This message is generated whenever + * the user moves the mouse in the view. This tells lets the document process it + * as well since the user could be dragging an object. + * + * @param inFlags The flags passed in from the message call + * @param inPoint The point where the event takes place + */ +//============================================================================== +void CPlayerContainerWnd::mouseMoveEvent(QMouseEvent* event) +{ + if (m_IsMouseDown) { + UICPROFILE(OnMouseMove); + + long theModifierKeys = 0; + if (event->buttons() & Qt::LeftButton) + theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers(); + else if (event->buttons() & Qt::RightButton) + theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers(); + + long theToolMode = g_StudioApp.GetToolMode(); + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag( + SceneDragSenderType::Matte, event->pos(), theToolMode, theModifierKeys); + } +} + +//============================================================================== +/** + * OnMouseWheel: Called whenever the mouse wheel. + * + * This processes the WM_MOUSEWHEEL message. + * + * @param inFlags the flags passed in from the message call + * @param inPoint the point where the event takes place + */ +//============================================================================== +void CPlayerContainerWnd::wheelEvent(QWheelEvent* event) +{ +#ifdef INCLUDE_EDIT_CAMERA + // Note : Mouse wheel is a special animal of the scene drag tool. We dont change the tool + // so as not to affect the toolbar button and the view cursor. This will just do the zoom + // and the cursor is not changed. + + const bool theCtrlKeyIsDown = event->modifiers() & Qt::ControlModifier; + const bool theAltKeyIsDown = event->modifiers() & Qt::AltModifier; + + // Keeping these codes here, till we finalized the behavior and confirm these not needed + // long theToolMode = g_StudioApp.GetToolMode( ); + //// If both the control key and the Alt key is not down + // if ( !theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView( ) ) + //{ + // if ( theToolMode != STUDIO_TOOLMODE_CAMERA_ZOOM ) + // { + // g_StudioApp.SetToolMode( STUDIO_TOOLMODE_CAMERA_ZOOM ); + // theToolMode = STUDIO_TOOLMODE_CAMERA_ZOOM; + // m_MouseWheeling = true; + + // Q_EMIT toolChanged(); + // SetViewCursor( ); + // } + //} + + // Mouse Wheel + // Do Camera Zoom + if (!theCtrlKeyIsDown && !theAltKeyIsDown && !IsDeploymentView()) + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseWheel( + SceneDragSenderType::Matte, event->delta(), STUDIO_TOOLMODE_CAMERA_ZOOM); +#else + Q_UNUSED(event); +#endif +} + +void CPlayerContainerWnd::scrollContentsBy(int, int) +{ + long x, y; + SetPlayerWndPosition(x, y); +} + +//============================================================================== +/** + * Set the view mode of the current scene view, whether we are in editing mode + * or deployment mode. For editing mode, we want to use the full scene area without + * any matte area. + * @param inViewMode the view mode of this scene + */ +void CPlayerContainerWnd::SetViewMode(EViewMode inViewMode) +{ + m_ViewMode = inViewMode; + m_SceneView->RecheckSizingMode(); + if (m_ViewMode == VIEW_SCENE) { + // switching from edit mode to deployment mode, release the edit camera tool and set it to + // object move + long theCurrentToolSettings = g_StudioApp.GetToolMode(); + bool theIsCameraTool = (theCurrentToolSettings & STUDIO_CAMERATOOL_MASK ? true : false); + if (theIsCameraTool) { + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE); + m_SceneView->SetToolMode(STUDIO_TOOLMODE_MOVE); + } + } +} + +//============================================================================== +/** + * return the view mode of the current scene view, whether we are in editing mode + * or deployment mode. For editing mode, we want to use the full scene area without + * any matte area. + * @return the current view mode + */ +CPlayerContainerWnd::EViewMode CPlayerContainerWnd::GetViewMode() +{ + return m_ViewMode; +} + +//============================================================================== +/** + * Checks whether we are in deployment view mode. + * @return true if is in deployment view mode, else false + */ +bool CPlayerContainerWnd::IsDeploymentView() +{ + return m_ViewMode == VIEW_SCENE ? true : false; +} + +QSize CPlayerContainerWnd::GetEffectivePresentationSize() const +{ + CPt cSize = g_StudioApp.GetCore()->GetStudioProjectSettings()->GetPresentationSize(); + QSize theSize(cSize.x, cSize.y); + + // If we have guides, resize the window with enough space for the guides as well as the + // presentation + // This is a very dirty hack because we are of course hardcoding the size of the guides. + // If the size of the guides never changes, the bet paid off. + if (g_StudioApp.GetRenderer().AreGuidesEnabled()) { + theSize += QSize(32, 32); + } + + return theSize / devicePixelRatio(); +} + +//============================================================================== + +void CPlayerContainerWnd::SetPlayerWnd(CPlayerWnd *inPlayerWnd) +{ + m_PlayerWnd = inPlayerWnd; + viewport()->setBackgroundRole(QPalette::Dark); + m_PlayerWnd->SetContainerWnd(this); + m_PlayerWnd->setParent(viewport()); + m_PlayerWnd->setVisible(true); + m_PlayerWnd->resize(m_PlayerWnd->sizeHint()); +} + +//============================================================================== +/** + * OnSize: Handles the WM_SIZE message + * + * Recenters the Client and recaluclates the matte when a resize message is + * generated. + * + * @param nType Specifies the type of resizing requested. + * @param cx Specifies the new width of the client area. + * @param cy Specifies the new height of the client area. + */ +//============================================================================== +void CPlayerContainerWnd::resizeEvent(QResizeEvent* event) +{ + QAbstractScrollArea::resizeEvent(event); + +#ifdef INCLUDE_EDIT_CAMERA + SetScrollRanges(); +#endif +} diff --git a/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h new file mode 100644 index 00000000..d4ac3cf5 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PlayerContainerWnd.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PLAYER_CONTAINER_WND_H +#define INCLUDED_PLAYER_CONTAINER_WND_H 1 + +#pragma once + +#include <QScrollArea> + +class CSceneView; +class CStudioApp; +class CPlayerWnd; +class CWGLRenderContext; + +//============================================================================== +// Class CPlayerContainerWnd +//============================================================================== + +class CPlayerContainerWnd : public QAbstractScrollArea +{ + Q_OBJECT + //============================================================================== + // Typedefs + //============================================================================== +public: + typedef enum { + VIEW_EDIT = 0, ///< Edit View + VIEW_SCENE, ///< Scene View + } EViewMode; + +public: + CPlayerContainerWnd(CSceneView *inSceneView); + virtual ~CPlayerContainerWnd(); + + void SetPlayerWnd(CPlayerWnd *inPlayerWnd); + void SetPlayerWndPosition(long &outLeftPresentationEdge, long &outTopPresentionEdge); + void SetScrollRanges(); + void RecenterClient(); + void OnRulerGuideToggled(); + + void SetViewMode(EViewMode inViewMode); + EViewMode GetViewMode(); + bool IsDeploymentView(); + + QRect GetDisplayedClientRect() const { return m_ClientRect; } + bool IsMouseDown() const { return m_IsMouseDown; } + bool IsMiddleMouseDown() const { return m_IsMiddleMouseDown; } + + QSize GetEffectivePresentationSize() const; + +Q_SIGNALS: + void toolChanged(); + +protected: + void resizeEvent(QResizeEvent *) override; + void mousePressEvent(QMouseEvent *) override; + void mouseReleaseEvent(QMouseEvent *) override; + void mouseMoveEvent(QMouseEvent *) override; + void wheelEvent(QWheelEvent *) override; + + void scrollContentsBy(int, int) override; + +private: + CPlayerContainerWnd() {} + bool ShouldHideScrollBars(); + +protected: + CSceneView *m_SceneView; ///< Pointer to the SceneView for rulers manipulation + CPlayerWnd *m_PlayerWnd; ///< Pointer to the window control that contains client + QRect m_ClientRect; ///< The rect where the client is drawn + bool m_IsMouseDown; ///< true if the mouse (any button) is down + bool m_IsMiddleMouseDown; ///< true if the middle mouse ( or scroll wheel ) is down + EViewMode m_ViewMode; +}; + +#endif // INCLUDED_PLAYER_CONTAINER_WND_H diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp new file mode 100644 index 00000000..ca9c7c51 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.cpp @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "PlayerWnd.h" +#include "MainFrm.h" +#include "SceneView.h" +#include "Dispatch.h" +#include "MasterP.h" +#include "HotKeys.h" +#include "StudioApp.h" +#include "Doc.h" +#include "Dispatch.h" +#include "HotKeys.h" +#include "MouseCursor.h" +#include "ResourceCache.h" +#include "SceneDropTarget.h" +#include "Core.h" +#include "IDragable.h" +#include "WGLRenderContext.h" +#include "IStudioRenderer.h" + +#include <QMouseEvent> + +//============================================================================== +// Class CPlayerWnd +//============================================================================== + +CPlayerWnd::CPlayerWnd(QWidget *parent) + : QOpenGLWidget(parent) + , m_ContainerWnd(nullptr) + , m_IsMouseDown(false) + , m_PreviousToolMode(0) + , m_FitClientToWindow(false) +{ + m_LastKnownMousePosition = QPoint(-1, -1); + + setAcceptDrops(true); + RegiserForDnd(this); + AddMainFlavor(EUIC_FLAVOR_FILE); + AddMainFlavor(EUIC_FLAVOR_ASSET_UICFILE); + AddMainFlavor(EUIC_FLAVOR_ASSET_LIB); + AddMainFlavor(EUIC_FLAVOR_BASIC_OBJECTS); + + setFormat(CWGLRenderContext::selectSurfaceFormat(this)); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CPlayerWnd::~CPlayerWnd() +{ +} + +//============================================================================== +/** + * OnMouseMove: Handle the WM_MOUSEMOVE message + * + * @param inFlags flags passed in with th mouse move message + * @param inPoint where the mouse is + */ +//============================================================================== +void CPlayerWnd::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::MiddleButton) { + // Middle button events are handled by the parent CPlayerContainerWnd + event->ignore(); + } else { + if (m_IsMouseDown) { + long theModifierKeys = 0; + if (event->buttons() & Qt::LeftButton) + theModifierKeys = CHotKeys::MOUSE_LBUTTON | CHotKeys::GetCurrentKeyModifiers(); + else if (event->buttons() & Qt::RightButton) + theModifierKeys = CHotKeys::MOUSE_RBUTTON | CHotKeys::GetCurrentKeyModifiers(); + + long theToolMode = g_StudioApp.GetToolMode(); + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDrag( + SceneDragSenderType::SceneWindow, event->pos(), theToolMode, theModifierKeys); + } else { + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseMove( + SceneDragSenderType::SceneWindow, event->pos()); + } + } +} + +//============================================================================== +/** + * OnSize: Handle the WM_SIZE message + * + * @param nType Passed to the base class + * @param cx change in x window size + * @param cy change in y window size + */ +//============================================================================== +void CPlayerWnd::resizeEvent(QResizeEvent *event) +{ + QOpenGLWidget::resizeEvent(event); +#ifdef KDAB_TEMPORARILY_REMOVED + CWnd *theChildWnd = this->GetWindow(GW_CHILD); + + if (theChildWnd != nullptr) { + CRect theWndRect; + + // Set the child window at the same position as the parent + this->GetWindowRect(&theWndRect); + + theChildWnd->ScreenToClient(&theWndRect); + theChildWnd->MoveWindow(&theWndRect, FALSE); + } +#endif + update(); +} + +//============================================================================== +/** + * OnLButtonDown: Handle the WM_LBUTTONDOWN message + * + * @param inFlags Flags passed in from the message + * @param inPoint The point wher the button was clicked + */ +//============================================================================== +void CPlayerWnd::mousePressEvent(QMouseEvent *event) +{ + const Qt::MouseButton btn = event->button(); + if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) { + long theToolMode = g_StudioApp.GetToolMode(); + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDown(SceneDragSenderType::SceneWindow, + event->pos(), theToolMode); + m_IsMouseDown = true; + } else if (btn == Qt::MiddleButton) { + event->ignore(); + } +} + +//============================================================================== +/** + * OnLButtonUp: Called whenever the user releases the left mouse button. + * + * This processes the WM_LBUTTONUP message. This message is generated whenever + * the left mouse button. We release the mouse capture to stop dragging. + * + * @param inFlags the flags passed in from the message call + * @param the point where the lbutton up takes place + */ +//============================================================================== +void CPlayerWnd::mouseReleaseEvent(QMouseEvent *event) +{ + const Qt::MouseButton btn = event->button(); + if ((btn == Qt::LeftButton) || (btn == Qt::RightButton)) { + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseUp(SceneDragSenderType::SceneWindow); + g_StudioApp.GetCore()->CommitCurrentCommand(); + m_IsMouseDown = false; + } else if (btn == Qt::MiddleButton) { + event->ignore(); + } +} + +void CPlayerWnd::mouseDoubleClickEvent(QMouseEvent *event) +{ + g_StudioApp.GetCore()->GetDispatch()->FireSceneMouseDblClick( + SceneDragSenderType::SceneWindow, event->pos()); +} + + +bool CPlayerWnd::OnDragWithin(CDropSource &inSource) +{ + CSceneViewDropTarget theTarget; + return theTarget.Accept(inSource); +} +bool CPlayerWnd::OnDragReceive(CDropSource &inSource) +{ + CSceneViewDropTarget theTarget; + Q_EMIT dropReceived(); + return theTarget.Drop(inSource); +} +void CPlayerWnd::OnDragLeave() +{ +} + +//============================================================================== +/** + * SetContainerWnd: keep track of a pointer to the containing window + * + * @param inContainerWnd pointer to what the containing window will be set to + */ +//============================================================================== +void CPlayerWnd::SetContainerWnd(CPlayerContainerWnd *inContainerWnd) +{ + m_ContainerWnd = inContainerWnd; + updateGeometry(); +} + +QSize CPlayerWnd::sizeHint() const +{ + if (m_ContainerWnd) + return m_ContainerWnd->GetEffectivePresentationSize(); + else + return QOpenGLWidget::sizeHint(); +} + +void CPlayerWnd::initializeGL() +{ + Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer()); + if (theRenderer.IsInitialized() == false) { + try { + theRenderer.Initialize(this); + } catch (...) { +#ifdef KDAB_TEMPORARILY_REMOVED + + wchar_t theBufferString[MAX_ENTRY_LENGTH]; + + _aswprintf(theBufferString, MAX_ENTRY_LENGTH - 1, + L"Unable to initialize OpenGL.\nThis may be because your graphic device is " + L"not sufficient, or simply because your driver is too old.\n\nPlease try " + L"upgrading your graphics driver and try again."); + ::wcsncat(theBufferString, L"\r\n\r\n", MAX_ENTRY_LENGTH - 1); + + ::MessageBoxW(nullptr, theBufferString, L"Fatal Error", + MB_OK | MB_ICONSTOP | MB_DEFBUTTON1); +#endif + exit(1); + } + } +} + +void CPlayerWnd::paintGL() +{ + Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer()); + // don't use request render here, this has to be + // synchronous inside paintGL + theRenderer.RenderNow(); +} + +void CPlayerWnd::resizeGL(int width, int height) +{ + // this also passes the new FBO to the CWGLContext + Q3DStudio::IStudioRenderer &theRenderer(g_StudioApp.GetRenderer()); + theRenderer.SetViewRect(QRect(0, 0, width * devicePixelRatio(), + height * devicePixelRatio())); +} diff --git a/src/Authoring/Studio/_Win/UI/PlayerWnd.h b/src/Authoring/Studio/_Win/UI/PlayerWnd.h new file mode 100644 index 00000000..25dfd949 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PlayerWnd.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PLAYERWND_H +#define INCLUDED_PLAYERWND_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== +#include "DropContainer.h" +#include "PlayerContainerWnd.h" + +#include <QOpenGLWidget> + +//============================================================================== +// Forwards +//============================================================================== +class CPlayerContainerWnd; +class CStudioApp; +class CMouseCursor; +class CHotkeys; + +//============================================================================== +// Class CPlayerWnd +//============================================================================== + +class CPlayerWnd : public QOpenGLWidget, public CWinDropContainer +{ + Q_OBJECT +public: + explicit CPlayerWnd(QWidget *parent = nullptr); + ~CPlayerWnd(); + + void SetContainerWnd(CPlayerContainerWnd *inSceneView); + + QSize sizeHint() const override; + + bool OnDragWithin(CDropSource &inSource) override; + bool OnDragReceive(CDropSource &inSource) override; + void OnDragLeave() override; + void OnReflectMouse(CPt &inPoint, Qt::KeyboardModifiers inFlags) override {} + +protected: + + CPlayerContainerWnd *m_ContainerWnd; + bool m_IsMouseDown; + long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch + ///back to previous mode on release) + bool m_FitClientToWindow; ///< True if we are in Fit to Window Mode + + QPoint m_LastKnownMousePosition; + +Q_SIGNALS: + void dropReceived(); + +protected: + void mouseMoveEvent(QMouseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseDoubleClickEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + + void initializeGL() override; + void paintGL() override; + void resizeGL(int width, int height) override; +}; + +#endif // INCLUDED_PLAYERWND_H diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.cpp b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp new file mode 100644 index 00000000..f0b5d2cd --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PopupWnd.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "PopupWnd.h" +#include "AppFonts.h" + +#include "StudioPreferences.h" + +//============================================================================== +/** + * Constructor: Initialize the object. + * + * Creates default fonts, colors, etc. + */ +CPopupWnd::CPopupWnd() + : m_CenterPt(0, 0) + , m_IsStationary(false) +{ + // get the proper font from appfonts + m_Font = CAppFonts::GetInstance()->GetNormalFont(); + + // Set the default colors (use default system tooltip colors) + m_TextColor = ::GetSysColor(COLOR_INFOTEXT); + m_BkColor = ::GetSysColor(COLOR_INFOBK); + ::CColor theBGColor(CStudioPreferences::GetTooltipBackgroundColor()); + m_BkColor = theBGColor.GetRGBColor(); + m_BkBrush = new CBrush(); + m_BkBrush->CreateSolidBrush(m_BkColor); +} + +//============================================================================== +/** + * Destructor: Destroys the object and releases associated memory. + */ +CPopupWnd::~CPopupWnd() +{ + // Clean up GDI objects + + // m_Font.DeleteObject(); + + if (m_BkBrush) { + DeleteObject(m_BkBrush); + delete m_BkBrush; + } +} + +//============================================================================== +// Message Map +//============================================================================== +BEGIN_MESSAGE_MAP(CPopupWnd, CWnd) +//{{AFX_MSG_MAP(CPopupWnd) +ON_WM_PAINT() +ON_WM_ERASEBKGND() +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +/** + * OnPaint: Handles the WM_PAINT windows message. + * + * Calls GetWindowText() and draws the text to the screen. + */ +void CPopupWnd::OnPaint() +{ + CPaintDC theDC(this); // device context for painting + CString theText; + + GetWindowText(theText); + if (theText.GetLength() > 0) { + + // Change the font + CFont *theOldFont = theDC.SelectObject(m_Font); + theDC.SetTextColor(m_TextColor); + theDC.SetBkColor(m_BkColor); + + // Paint the text + CRect theClientRect; + this->GetClientRect(theClientRect); + theDC.DrawText(theText, theClientRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE); + + // Restore original font + theDC.SelectObject(theOldFont); + } +} + +//============================================================================== +/** + * SetWindowText: Sets the text for this window. + * + * Overridden from parent so that we can calculate how big we need to make the + * pop-up window so that the text fits. Automatically adjusts the window + * size/position to fit the new text string. + */ +void CPopupWnd::SetWindowText(LPCTSTR lpszString) +{ + CString theNewText; + theNewText.Format(L" %s ", lpszString); + + // Set the window text + CWnd::SetWindowText(theNewText); + + // Calculate the new window rect with the specified text + CDC *theDC = GetDC(); + CRect theRect(0, 0, 1, 1); + CFont *theOldFont = theDC->SelectObject(m_Font); + + theDC->DrawText(theNewText, theRect, DT_CALCRECT); + theDC->SelectObject(theOldFont); + ::AdjustWindowRect(theRect, this->GetStyle(), FALSE); + CPoint theTopLeft = theRect.TopLeft(); + CPoint theBottomRight = theRect.BottomRight(); + ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft); + ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight); + CRect theAdjustedRect(theTopLeft, theBottomRight); + int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x); + int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y); + + ReleaseDC(theDC); + + // Move the window to the new position, with the new size, still centered at m_CenterPt + this->SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(), + SWP_NOZORDER | SWP_NOACTIVATE); +} + +//============================================================================== +/** + * SetCenterPoint: Changes the center of this window. + * + * Use this function to specify where you want the center of the pop-up window + * to appear. The window is automatically moved to the new center position. + */ +void CPopupWnd::SetCenterPoint(CPoint inPoint) +{ + if ((m_IsStationary && !IsWindowVisible()) || !m_IsStationary) { + // Store the center point + m_CenterPt = inPoint; + + // Calculate the new window position so that it is centered at the new point + CRect theWindowRect; + this->GetWindowRect(theWindowRect); + CPoint theTopLeft = theWindowRect.TopLeft(); + CPoint theBottomRight = theWindowRect.BottomRight(); + ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theTopLeft); + ::ClientToScreen(this->GetParent()->GetSafeHwnd(), &theBottomRight); + CRect theAdjustedRect(theTopLeft, theBottomRight); + int theX = abs((int)(theAdjustedRect.Width() / 2) - m_CenterPt.x); + int theY = abs((int)(theAdjustedRect.Height() / 2) - m_CenterPt.y); + + // Move the window + SetWindowPos(nullptr, theX, theY, theAdjustedRect.Width(), theAdjustedRect.Height(), + SWP_NOZORDER | SWP_NOACTIVATE); + } +} + +//============================================================================== +/** + * SetBkColor: Changes the background color of this window. + * + * Defaults to COLOR_INFOBK (tooltip background color). Creates a brush used + * in OnEraseBkgnd() of the specified color. + * + * @param inColor The new background color. + */ +void CPopupWnd::SetBkColor(COLORREF inColor) +{ + m_BkColor = inColor; + + // If we already have a background brush + if (m_BkBrush) { + // Kill it + DeleteObject(m_BkBrush); + delete m_BkBrush; + } + + // Make a brush of the specified color + m_BkBrush = new CBrush(); + m_BkBrush->CreateSolidBrush(m_BkColor); +} + +//============================================================================== +/** + * OnEraseBkgnd: Handles the WM_ERASEBKGND windows message. + * Redraws the client rect using the current background brush. + * + * @param pDC Pointer to a display context for drawing. + * @return TRUE. + */ +BOOL CPopupWnd::OnEraseBkgnd(CDC *pDC) +{ + // Erase the client rect using the background brush so it's the right color + CRect theClientRect; + this->GetClientRect(theClientRect); + pDC->FillRect(theClientRect, m_BkBrush); + return TRUE; +} + +//============================================================================== +/** + * UpdateToolTip: Allows you to change multiple properties on this window at once. + * + * @param inCenter New center point of the popup window + * @param inText New window text for the window + * @param inShowWindow true to show the window, false to hide the window + */ +void CPopupWnd::UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow) +{ + int theShowFlag = (inShowWindow) ? SW_SHOWNA : SW_HIDE; + + this->SetCenterPoint(inCenter); + this->SetWindowText(inText); + this->ShowWindow(theShowFlag); + this->Invalidate(FALSE); + this->UpdateWindow(); +} diff --git a/src/Authoring/Studio/_Win/UI/PopupWnd.h b/src/Authoring/Studio/_Win/UI/PopupWnd.h new file mode 100644 index 00000000..da58c9b1 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PopupWnd.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_POP_UP_WND +#define INCLUDED_POP_UP_WND 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +//============================================================================== +/** + * CPopupWnd: Class for making pop-up windows (a replacement for tooltips). + * + * To use, just create a CPopupWnd, set the text that you want displayed, then + * call ShowWindow() to toggle the window on and off. Default color scheme of + * this window mimics the system settings for tooltips. + */ +class CPopupWnd : public CWnd +{ +public: + CPopupWnd(); + + virtual ~CPopupWnd(); + + /// Sets the text to display in this window + void SetWindowText(LPCTSTR lpszString); + + /// Sets the center point of this window in screen coordinates + void SetCenterPoint(CPoint inPoint); + + /// Sets the center point of this window from an x,y pair (screen coordinates) + void SetCenterPoint(int inX, int inY) { SetCenterPoint(CPoint(inX, inY)); } + + /// Retrieves the center point of this window (screen coordinates) + CPoint GetCenterPoint() { return m_CenterPt; } + + /// Sets the color of the text + void SetTextColor(COLORREF inColor) { m_TextColor = inColor; } + + /// Sets the background color of the window + void SetBkColor(COLORREF inColor); + + /// Returns a pointer to the CFont object used to draw the text. You can make changes to the + /// font using the pointer that's returned, + /// just don't delete it. The default font is set in the constructor as Arial 13. + CFont *GetFont() { return m_Font; } + + /// Allows you to change multiple properties on this window at once. + void UpdateToolTip(CPoint inCenter, CString inText, bool inShowWindow); + + /// + void SetStationary(bool inIsStationary) { m_IsStationary = inIsStationary; } + +protected: + CPoint m_CenterPt; ///< Center of this window in screen coordinates + CFont *m_Font; ///< Font for the window text + COLORREF m_TextColor; ///< Color of the text + COLORREF m_BkColor; ///< Background color of the window + CBrush *m_BkBrush; ///< Brush used for paiting the background of the window + bool m_IsStationary; ///< If the window is stationary, then it can only be moved while it is not + ///showing + + // Generated message map functions +protected: + //{{AFX_MSG(CPopupWnd) + afx_msg void OnPaint(); + afx_msg BOOL OnEraseBkgnd(CDC *pDC); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#endif // INCLUDED_POP_UP_WND diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp new file mode 100644 index 00000000..649efa8c --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.cpp @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================= +// Prefix +//============================================================================= +#include "stdafx.h" + +#pragma warning(disable : 4127) + +//============================================================================== +// Includes +//============================================================================== +#include "PreviewOutputDlg.h" +#include "StudioClipboard.h" +#include "UICFileTools.h" +#include "StudioApp.h" +#include "Doc.h" +#include "Mainfrm.h" +#include "Dialogs.h" +#include "Strings.h" +#include "Resource.h" +#include "Core.h" + +// CPreviewOutput dialog + +IMPLEMENT_DYNAMIC(CPreviewOutputDlg, CDialog) + +CPreviewOutputDlg::CPreviewOutputDlg(const Q3DStudio::CString &inCmd, + const Q3DStudio::CString &inExportedFile, + CPreviewHelper::EExecMode inViewMode) + : CDialog(CPreviewOutputDlg::IDD, nullptr) + , m_Cmd(inCmd) + , m_ExportedFile(inExportedFile) + , m_ViewMode(inViewMode) + , m_ReadThreadHandle(nullptr) + , m_PreviewProcessHandle(nullptr) +{ + m_OutputReadThreadParam.m_ReadHandle = nullptr; + m_OutputReadThreadParam.m_Context = nullptr; +} + +CPreviewOutputDlg::~CPreviewOutputDlg() +{ + if (m_ReadThreadHandle) { + TerminateThread(m_ReadThreadHandle, 0); + m_ReadThreadHandle = nullptr; + } + + if (m_OutputReadThreadParam.m_ReadHandle) { + CloseHandle(m_OutputReadThreadParam.m_ReadHandle); + m_OutputReadThreadParam.m_ReadHandle = nullptr; + } +} + +void CPreviewOutputDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_LIST_PREVIEW_STATUS, m_ListCtrl); +} + +//============================================================================= +/** + * Message Handler when dialog is initially opened. + */ +//============================================================================= +BOOL CPreviewOutputDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Set the dialog header + Q3DStudio::CString theFile = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetName(); + if (theFile == "") + theFile = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE); + Q3DStudio::CString theDlgHeader; + Q3DStudio::CString theOperation; + switch (m_ViewMode) { + case CPreviewHelper::EXECMODE_PREVIEW: + theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW); + break; + + case CPreviewHelper::EXECMODE_DEPLOY: + theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY); + break; + } + theDlgHeader.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_TITLE), + static_cast<const wchar_t *>(theOperation), + static_cast<const wchar_t *>(theFile)); + SetWindowText(theDlgHeader); + + // Prepare the list control + COLORREF theColor = 0x00C0C0C0; + m_ListCtrl.SetBkColor(theColor); + m_ListCtrl.SetTextBkColor(theColor); + CRect theRect; + m_ListCtrl.GetClientRect(theRect); + m_ListCtrl.InsertColumn(0, L"", LVCFMT_LEFT, + theRect.Width() * 2); // Double the width to see more + + // Start the preview + if (!ExecutePreview()) { + CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), m_ExportedFile); + Q3DStudio::CString theMessage; + theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_MSG), + static_cast<const wchar_t *>(thePreviewerFile.GetAbsolutePosixPath())); + g_StudioApp.GetDialogs()->DisplayMessageBox( + ::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TITLE), theMessage, + CUICMessageBox::ICON_ERROR, false); + } + + return TRUE; +} + +//============================================================================= +/** + * Handler for copying + */ +//============================================================================= +void CPreviewOutputDlg::OnCopyText() +{ + try { + Q3DStudio::CString theText = ""; + int theNumEntry = m_ListCtrl.GetItemCount(); + for (int theIndex = 0; theIndex < theNumEntry; ++theIndex) { + theText += m_ListCtrl.GetItemText(theIndex, 0); + theText += "\r\n"; + } + CStudioClipboard::CopyTextToClipboard(theText); + } catch (...) { + } +} + +//============================================================================= +/** + * Handler for OK Button + */ +//============================================================================= +void CPreviewOutputDlg::OnOK() +{ + TerminateThread(m_ReadThreadHandle, 0); + CDialog::OnOK(); + m_ReadThreadHandle = nullptr; +} + +BEGIN_MESSAGE_MAP(CPreviewOutputDlg, CDialog) +ON_BN_CLICKED(IDC_BUTTON_COPY_TEXT, OnCopyText) +END_MESSAGE_MAP() + +//============================================================================== +/** + * Spawn the process to execute the preview operation and redirect it's output + * to the list control + */ +//============================================================================== +BOOL CPreviewOutputDlg::ExecutePreview() +{ + HANDLE theOutputReadHandleTmp; + HANDLE theOutputReadHandle; + HANDLE theOutputWriteHandle; + + // Set up the security attributes struct. + SECURITY_ATTRIBUTES theSecurityAttr; + theSecurityAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + theSecurityAttr.lpSecurityDescriptor = nullptr; + theSecurityAttr.bInheritHandle = TRUE; + + // Create the child output pipe. + if (!CreatePipe(&theOutputReadHandleTmp, &theOutputWriteHandle, &theSecurityAttr, 0)) + return FALSE; + + // Create new output read handle. Set the Properties to FALSE. + // Otherwise, the child inherits the properties and, as a result, + // non-closeable handles to the pipes are created. + if (!DuplicateHandle(GetCurrentProcess(), theOutputReadHandleTmp, GetCurrentProcess(), + &theOutputReadHandle, // Address of new handle. + 0, FALSE, // Make it uninheritable. + DUPLICATE_SAME_ACCESS)) + return FALSE; + + // Close inheritable copies of the handles you do not want to be inherited. + CloseHandle(theOutputReadHandleTmp); + + LaunchPreviewProcess(theOutputWriteHandle, m_Cmd); + + // Close pipe handles (do not continue to modify the parent). + // You need to make sure that no handles to the write end of the + // output pipe are maintained in this process or else the pipe will + // not close when the child process exits and the ReadFile will hang. + CloseHandle(theOutputWriteHandle); + + // Spawn a thread to busy read the preivew process output. + DWORD theThreadId; + m_OutputReadThreadParam.m_Context = this; + m_OutputReadThreadParam.m_ReadHandle = theOutputReadHandle; + m_ReadThreadHandle = CreateThread(nullptr, 0, CPreviewOutputDlg::ReadOutputThread, + (LPVOID)&m_OutputReadThreadParam, 0, &theThreadId); + return TRUE; +} + +//============================================================================== +/** + * Callback when the preview operation has completed. + */ +//============================================================================== +void CPreviewOutputDlg::PreviewProcessTerminated() +{ + DWORD theExitCode; + GetExitCodeProcess(m_PreviewProcessHandle, &theExitCode); + if (theExitCode == 0) + PostMessage(WM_CLOSE); // close the window + else { + Q3DStudio::CString theOperation; + switch (m_ViewMode) { + case CPreviewHelper::EXECMODE_PREVIEW: + theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_PREVIEW); + break; + + case CPreviewHelper::EXECMODE_DEPLOY: + theOperation = ::LoadResourceString(IDS_CONFIG_EXPORT_DEPLOY); + break; + } + Q3DStudio::CString theMessage; + theMessage.Format(::LoadResourceString(IDS_CONFIG_PREVIEW_ERROR_TEXT), + static_cast<const wchar_t *>(theOperation)); + DisplayOutput(theMessage); + } +} + +//============================================================================== +/** + * Write the string into the list control. + * @param inString the string to display + */ +//============================================================================== +void CPreviewOutputDlg::DisplayOutput(CString inStr) +{ + const wchar_t *DELIMITERS = L"\r\t\n"; + + wchar_t theBuffer[512] = { 0 }; + ::wcscpy(theBuffer, inStr); + + wchar_t *theToken = ::wcstok(theBuffer, DELIMITERS); + while (theToken) { + m_ListCtrl.InsertItem(m_ListCtrl.GetItemCount(), theToken); + theToken = ::wcstok(nullptr, DELIMITERS); + } + + m_ListCtrl.EnsureVisible(m_ListCtrl.GetItemCount() - 1, FALSE); +} + +//============================================================================== +/** + * Spawn the process to execute the preview operation + * @param inStdOutput the handle to write the output to + * @param inCmd the command to execute + * @return true is spawned successfully, else false + */ +//============================================================================== +BOOL CPreviewOutputDlg::LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd) +{ + // Further usability hax, you love them. + DisplayOutput(L"Checking for .NET Framework install:"); + HKEY theHKey; + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, + L"SOFTWARE\\Microsoft\\NET Framework Setup\\NDP", 0, + KEY_QUERY_VALUE, &theHKey)) { + DisplayOutput(L" - OK: .NET Framework present."); + } else { + DisplayOutput(L" - WARNING: .NET Framework Missing?"); + } + + // Launch the process with the working directory set to the parent directory of current document + CUICFile theDocument = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath(); + + Q3DStudio::CString theWorkingPath; + if (theDocument.Exists()) + theWorkingPath = theDocument.GetAbsolutePath(); + else + theWorkingPath = m_ExportedFile; + + CUICFile thePreviewerFile(CUICFile::GetApplicationDirectory(), theWorkingPath); + Q3DStudio::CFilePath theWorkingDirectory(thePreviewerFile.GetAbsolutePosixPath()); + + PROCESS_INFORMATION theProcessInfo; + STARTUPINFO theStartupInfo; + + // Set up the start up info struct. + ZeroMemory(&theStartupInfo, sizeof(STARTUPINFO)); + theStartupInfo.cb = sizeof(STARTUPINFO); + theStartupInfo.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + theStartupInfo.hStdOutput = inStdOutput; + theStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE) /*hChildStdIn*/; + theStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + theStartupInfo.wShowWindow = SW_HIDE; + + if (!CreateProcess(nullptr, const_cast<wchar_t *>(inCmd.c_str()), nullptr, nullptr, TRUE, 0, nullptr, + theWorkingDirectory.GetDirectory(), &theStartupInfo, &theProcessInfo)) + return FALSE; + + // Close any unnecessary handles. + CloseHandle(theProcessInfo.hThread); + m_PreviewProcessHandle = theProcessInfo.hProcess; + return TRUE; +} + +//============================================================================== +/** + * Spawn the thread to busy read the output and write to the list control + * @param inThreadParam the parameter used by this thread + * @return 1 + */ +//============================================================================== +DWORD WINAPI CPreviewOutputDlg::ReadOutputThread(LPVOID inThreadParam) +{ + char theBuffer[512]; + DWORD theBytesRead; + SThreadParam *theParam = (SThreadParam *)inThreadParam; + HANDLE thePipeRead = theParam->m_ReadHandle; + CPreviewOutputDlg *theDlg = (CPreviewOutputDlg *)(theParam->m_Context); + + while (TRUE) { + if (!ReadFile(thePipeRead, theBuffer, sizeof(theBuffer) - sizeof(char), &theBytesRead, nullptr) + || !theBytesRead) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + theDlg->PreviewProcessTerminated(); + CloseHandle(thePipeRead); + theParam->m_ReadHandle = nullptr; + break; // pipe done - normal exit path. + } else + theDlg->DisplayOutput(::LoadResourceString( + IDS_CONFIG_PREVIEW_REDIRECT_ERROR)); // Something bad happened. + } else { + if (theBytesRead) { + theBuffer[theBytesRead] = '\0'; // Follow input with a nullptr. + theDlg->DisplayOutput(CString(theBuffer)); + } + } + } + return 1; +} diff --git a/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h new file mode 100644 index 00000000..19361d3d --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/PreviewOutputDlg.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_PREVIEW_OUTPUT_DIALOG_H +#define INCLUDED_PREVIEW_OUTPUT_DIALOG_H 1 + +//============================================================================== +// Includes +//============================================================================== +#include "resource.h" +#include "PreviewHelper.h" + +//============================================================================== +// Forwards +//============================================================================== +namespace Q3DStudio { +class CFilePath; +} + +class CPreviewOutputDlg : public CDialog +{ + DECLARE_DYNAMIC(CPreviewOutputDlg) + +protected: + struct SThreadParam + { + void *m_Context; + HANDLE m_ReadHandle; + }; + +public: + CPreviewOutputDlg(const Q3DStudio::CString &inCmd, const Q3DStudio::CString &inExportedFile, + CPreviewHelper::EExecMode inViewMode); + virtual ~CPreviewOutputDlg(); + + // Dialog Data + enum { IDD = IDD_DIALOG_PREVIEW_STATUS }; + CListCtrl m_ListCtrl; + +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + virtual void OnCopyText(); + virtual void OnOK(); + DECLARE_MESSAGE_MAP() + +protected: + BOOL ExecutePreview(); + BOOL LaunchPreviewProcess(HANDLE inStdOutput, Q3DStudio::CString &inCmd); + static DWORD WINAPI ReadOutputThread(LPVOID lpvThreadParam); + void DisplayOutput(CString inStr); + void PreviewProcessTerminated(); + +protected: + Q3DStudio::CString m_Cmd; + Q3DStudio::CString m_ExportedFile; + SThreadParam m_OutputReadThreadParam; + HANDLE m_PreviewProcessHandle; + HANDLE m_ReadThreadHandle; + CPreviewHelper::EExecMode m_ViewMode; +}; + +#endif // INCLUDED_PREVIEW_OUTPUT_DIALOG_H diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.cpp b/src/Authoring/Studio/_Win/UI/RecentItems.cpp new file mode 100644 index 00000000..b229ff29 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/RecentItems.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "stdafx.h" + +#include "RecentItems.h" +#include "Preferences.h" + +#include <QMenu> + +// using namespace Q3DStudio; <-- Do not do this here because it will conflict with CList and make +// the template generator go blah + +const Q3DStudio::CString CRecentItems::RECENTITEM_KEY = "RecentItem"; +const Q3DStudio::CString CRecentItems::RECENTIMPORT_KEY = "RecentImport"; +const Q3DStudio::CString CRecentItems::RECENTITEM_VALID = "RecentValid"; + +CRecentItems::CRecentItems(QMenu *inMenuID, long inCommandID, Q3DStudio::CString inPreferenceKey) +{ + Q_UNUSED(inCommandID) + + m_Menu = inMenuID; + m_ValidItems = 10; + m_PreferenceKey = inPreferenceKey; + + ReconstructList(); +} + +CRecentItems::~CRecentItems() +{ +} + +void CRecentItems::AddRecentItem(const CUICFile &inItem) +{ + RemoveRecentItem(inItem); + + m_RecentItems.insert(m_RecentItems.begin(), inItem); + + while (m_RecentItems.size() > 10) + m_RecentItems.pop_back(); + + RebuildList(); +} + +void CRecentItems::RemoveRecentItem(const CUICFile &inItem) +{ + TFileList::iterator thePos = m_RecentItems.begin(); + for (; thePos != m_RecentItems.end(); ++thePos) { + if ((*thePos) == inItem) { + m_RecentItems.erase(thePos); + break; + } + } + + RebuildList(); +} + +void CRecentItems::ReconstructList() +{ + ClearMenu(); + m_RecentItems.clear(); + + CPreferences thePrefs = CPreferences::GetUserPreferences(); + + m_ValidItems = thePrefs.GetLongValue(RECENTITEM_VALID, m_ValidItems); + + for (long theIndex = 0; theIndex < (m_ValidItems > 10 ? 10 : m_ValidItems); ++theIndex) { + Q3DStudio::CString theKey; + theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex); + + Q3DStudio::CString theFilename = thePrefs.GetStringValue(theKey, ""); + if (theFilename != "") { + CUICFile theFile(theFilename); + + QAction *act = m_Menu->addAction(theFile.GetName().toQString(), + this, &CRecentItems::onTriggerRecent); + act->setData(static_cast<int>(m_RecentItems.size())); + m_RecentItems.push_back(theFile); + } + } +} + +void CRecentItems::RebuildList() +{ + ClearMenu(); + + CPreferences thePrefs = CPreferences::GetUserPreferences(); + thePrefs.SetLongValue(RECENTITEM_VALID, GetItemCount()); + TFileList::iterator thePos = m_RecentItems.begin(); + for (long theIndex = 0; thePos != m_RecentItems.end(); ++thePos, ++theIndex) { + Q3DStudio::CString theFilename = (*thePos).GetName(); + + QAction *act = m_Menu->addAction(theFilename.toQString(), + this, &CRecentItems::onTriggerRecent); + act->setData(static_cast<int>(theIndex)); + + Q3DStudio::CString theKey; + theKey.Format(_UIC("%ls%d"), static_cast<const wchar_t *>(m_PreferenceKey), theIndex); + + thePrefs.SetStringValue(theKey, (*thePos).GetAbsolutePath()); + } +} + +void CRecentItems::ClearMenu() +{ + m_Menu->clear(); +} + +CUICFile CRecentItems::GetItem(long inIndex) +{ + return m_RecentItems.at(inIndex); +} + +void CRecentItems::onTriggerRecent() +{ + const int index = qobject_cast<QAction *>(sender())->data().toInt(); + Q_EMIT openRecent(index); +} + diff --git a/src/Authoring/Studio/_Win/UI/RecentItems.h b/src/Authoring/Studio/_Win/UI/RecentItems.h new file mode 100644 index 00000000..bc295079 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/RecentItems.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_RECENT_ITEMS_H +#define INCLUDED_RECENT_ITEMS_H 1 + +#pragma once + +#include <QObject> + +#include "UICString.h" +#include "UICFile.h" + +#include <vector> + +class CUICFile; + +QT_BEGIN_NAMESPACE +class QMenu; +QT_END_NAMESPACE + +class CRecentItems : public QObject +{ + Q_OBJECT + + typedef std::vector<CUICFile> TFileList; + +public: + static const Q3DStudio::CString RECENTITEM_KEY; + static const Q3DStudio::CString RECENTIMPORT_KEY; + static const Q3DStudio::CString RECENTITEM_VALID; + +Q_SIGNALS: + void openRecent(int index); +public: + CRecentItems(QMenu *inMenu, long inCommandID, + Q3DStudio::CString inPreferenceKey = RECENTITEM_KEY); + virtual ~CRecentItems(); + + void AddRecentItem(const CUICFile &inItem); + void RemoveRecentItem(const CUICFile &inItem); + + CUICFile GetItem(long inIndex); + long GetItemCount() const { return (long)m_RecentItems.size(); } + +protected: + void ClearMenu(); + void ReconstructList(); + void RebuildList(); + void SaveRecentList(); + + TFileList m_RecentItems; + + long m_CommandID; + long m_ValidItems; + QMenu *m_Menu; + Q3DStudio::CString m_PreferenceKey; + +private Q_SLOTS: + void onTriggerRecent(); +}; +#endif // INCLUDED_RECENT_ITEMS_H diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.cpp b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp new file mode 100644 index 00000000..2563a4c1 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ReportDlg.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// ReportDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "Strings.h" + +#include "ReportDlg.h" +#include "CrashInfo.h" + +#include "CompConfig.h" + +#include "StudioInstance.h" +#include <strstream> + +extern char g_DumpPath[MAX_PATH]; +///////////////////////////////////////////////////////////////////////////// +// CReportDlg dialog + +CReportDlg::CReportDlg(CWnd *pParent /*=nullptr*/) + : CDialog(CReportDlg::IDD, pParent) + , m_SysInfoText(_T("")) +{ + //{{AFX_DATA_INIT(CReportDlg) + m_Info = _T(""); + m_DescHeader = _T(""); + m_EmailAddress = _T(""); + m_EmailHeader = _T(""); + //}}AFX_DATA_INIT + + m_MediumFont2.CreatePointFont(88, CString(CStudioPreferences::GetFontFaceName())); + + m_Color_Background = CStudioPreferences::GetDarkBaseColor(); + m_Color_Text = CStudioPreferences::GetMasterColor(); + m_Color_Gray = CStudioPreferences::GetNormalColor(); + m_Color_Dark = CStudioPreferences::GetInactiveColor(); +} + +void CReportDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CReportDlg) + DDX_Control(pDX, IDC_REPORTDLG_SYSINFO, m_SendSysInfo); + DDX_Control(pDX, IDC_REPORTDLG_DESC, m_Description); + DDX_Text(pDX, IDC_REPORTDLG_INFO, m_Info); + DDX_Text(pDX, IDC_REPORTDLG_DESCHEADER, m_DescHeader); + DDX_Text(pDX, IDC_REPORTDLG_EMAILADDR, m_EmailAddress); + DDX_Text(pDX, IDC_REPORTDLG_EMAILHEADER, m_EmailHeader); + //}}AFX_DATA_MAP + DDX_Text(pDX, IDC_CRASHDLG_SYSINFO_TEXT, m_SysInfoText); +} + +BEGIN_MESSAGE_MAP(CReportDlg, CDialog) +//{{AFX_MSG_MAP(CReportDlg) +ON_BN_CLICKED(IDSUBMIT, OnSubmit) +//}}AFX_MSG_MAP +ON_WM_CTLCOLOR() +ON_WM_ERASEBKGND() +// ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg) +ON_STN_CLICKED(IDC_REPORTDLG__SYSINFO_TEXT, &CReportDlg::OnStnClickedReportdlg) +END_MESSAGE_MAP() + +//============================================================================== +/** + * Set the description of the crash. + * @param inErrorMessage the error message. + */ +//============================================================================== +void CReportDlg::SetErrorMessage(CString inErrorMessage) +{ + m_ErrorMessage = inErrorMessage; +} + +//============================================================================== +/** + * Set the stack trace for the crash. + * @param inStackTrace the stack trace. + */ +//============================================================================== +void CReportDlg::SetStackTrace(CString inStackTrace) +{ + m_StackTrace = inStackTrace; +} + +///////////////////////////////////////////////////////////////////////////// +// CReportDlg message handlers + +void CReportDlg::OnSubmit() +{ + CWaitCursor theWaitCursor; + + this->UpdateData(TRUE); + + // Actual reporting functionality missing + + this->EndDialog(TRUE); + exit(1); +} + +void CReportDlg::OnCancel() +{ + this->EndDialog(FALSE); +} + +BOOL CReportDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_Info = ::LoadResourceString(IDS_REPORTDLG_INFO).GetMulti(); + m_DescHeader = ::LoadResourceString(IDS_REPORTDLG_DESCHEADER).GetMulti(); + m_EmailHeader = ::LoadResourceString(IDS_REPORTDLG_EMAILHEADER).GetMulti(); + + CString theSysInfoText; + theSysInfoText = ""; //::LoadResourceString( IDS_REPORTDLG_SYSINFOHEADER ).GetMulti( ); + // this is done this way, as i had problem changing the color of the text of the checkbox. + // it is now a seperate checkbox and a static text + // Made a workaround where the static text has notify flag on and would toggle the checkbox + // control on and off + // when clicked + m_SysInfoText = ::LoadResourceString(IDS_REPORTDLG_SYSINFOHEADER).GetMulti(); + + m_SendSysInfo.SetWindowText(theSysInfoText); + m_SendSysInfo.SetFont(&m_MediumFont2); + m_SendSysInfo.SetCheck(BST_CHECKED); + + m_Brush.CreateSolidBrush(m_Color_Background); + GetDlgItem(IDC_REPORTDLG_INFO)->SetFont(&m_MediumFont2); + GetDlgItem(IDC_REPORTDLG_DESCHEADER)->SetFont(&m_MediumFont2); + GetDlgItem(IDC_REPORTDLG_EMAILADDR)->SetFont(&m_MediumFont2); + GetDlgItem(IDC_REPORTDLG_EMAILHEADER)->SetFont(&m_MediumFont2); + GetDlgItem(IDC_REPORTDLG__SYSINFO_TEXT)->SetFont(&m_MediumFont2); + + this->UpdateData(FALSE); + + return TRUE; +} + +HBRUSH CReportDlg::OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor) +{ + Q_UNUSED(nCtlColor); + + int theCtrlID = pWnd->GetDlgCtrlID(); + if (theCtrlID == IDSUBMIT || theCtrlID == IDCANCEL || theCtrlID == IDC_REPORTDLG_SEPERATOR + || theCtrlID == IDC_REPORTDLG_SYSINFO || theCtrlID == IDC_REPORTDLG__SYSINFO_TEXT + || theCtrlID == IDC_REPORTDLG_INFO || theCtrlID == IDC_REPORTDLG_DESCHEADER + || theCtrlID == IDC_REPORTDLG_EMAILHEADER) { + pDC->SetBkMode(TRANSPARENT); // for area just behind the text + pDC->SetTextColor(m_Color_Gray); + } else if (theCtrlID == IDC_REPORTDLG_DESC || theCtrlID == IDC_REPORTDLG_EMAILADDR) { + pDC->SetBkColor(m_Color_Background); + pDC->SetBkMode(OPAQUE); // for area just behind the text + pDC->SetTextColor(m_Color_Text); + } + + return m_Brush; +} + +BOOL CReportDlg::OnEraseBkgnd(CDC *pDC) +{ + CRect theClientRect; + GetClientRect(&theClientRect); + pDC->FillSolidRect(theClientRect, m_Color_Background); + + return TRUE; +} + +void CReportDlg::OnStnClickedReportdlg() +{ + m_SendSysInfo.SetCheck(!m_SendSysInfo.GetCheck()); +} diff --git a/src/Authoring/Studio/_Win/UI/ReportDlg.h b/src/Authoring/Studio/_Win/UI/ReportDlg.h new file mode 100644 index 00000000..c54743da --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ReportDlg.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_) +#define AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ReportDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CReportDlg dialog + +class CReportDlg : public CDialog +{ + // Construction +public: + CReportDlg(CWnd *pParent = nullptr); // standard constructor + + COLORREF m_Color_Background; + COLORREF m_Color_Text; + COLORREF m_Color_Gray; + COLORREF m_Color_Dark; + CBrush m_Brush; + CFont m_MediumFont2; + + // Dialog Data + //{{AFX_DATA(CReportDlg) + enum { IDD = IDD_REPORTDLG }; + CButton m_SendSysInfo; + CEdit m_Description; + CString m_Info; + CString m_DescHeader; + CString m_EmailAddress; + CString m_EmailHeader; + //}}AFX_DATA + + void SetErrorMessage(CString inErrorMessage); + void SetStackTrace(CString inStackTrace); + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CReportDlg) +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + // Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CReportDlg) + afx_msg void OnSubmit(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + CString m_ErrorMessage; + CString m_StackTrace; + +public: + afx_msg HBRUSH OnCtlColor(CDC *pDC, CWnd *pWnd, UINT nCtlColor); + afx_msg BOOL OnEraseBkgnd(CDC *pDC); + CString m_SysInfoText; + // afx_msg void OnStnClickedReportdlg(); + afx_msg void OnStnClickedReportdlg(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_REPORTDLG_H__B8564DEF_2599_4419_9E15_4AF38BE7066C__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp new file mode 100644 index 00000000..2eaa293a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#include "stdafx.h" +#include "ResetKeyframeValuesDlg.h" +#include ".\resetkeyframevaluesdlg.h" + +IMPLEMENT_DYNAMIC(CResetKeyframeValuesDlg, CDialog) +CResetKeyframeValuesDlg::CResetKeyframeValuesDlg(CWnd *pParent /*=nullptr*/) + : CDialog(CResetKeyframeValuesDlg::IDD, pParent) +{ +} + +CResetKeyframeValuesDlg::~CResetKeyframeValuesDlg() +{ +} + +void CResetKeyframeValuesDlg::DoDataExchange(CDataExchange *pDX) +{ + CDialog::DoDataExchange(pDX); + DDX_Control(pDX, IDC_RESETKEYFRAMEVALUES_DLG_ICON, m_WarningIcon); + DDX_Control(pDX, IDCANCEL, m_CancelButton); +} + +BEGIN_MESSAGE_MAP(CResetKeyframeValuesDlg, CDialog) +END_MESSAGE_MAP() + +BOOL CResetKeyframeValuesDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + m_WarningIcon.SetIcon(::AfxGetApp()->LoadStandardIcon(IDI_WARNING)); + m_CancelButton.SetButtonStyle(BS_DEFPUSHBUTTON); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h new file mode 100644 index 00000000..d0a883d1 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/ResetKeyframeValuesDlg.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Includes +//============================================================================== +#pragma once +#include "Resource.h" +#include "afxwin.h" + +class CResetKeyframeValuesDlg : public CDialog +{ + DECLARE_DYNAMIC(CResetKeyframeValuesDlg) + +public: + CResetKeyframeValuesDlg(CWnd *pParent = nullptr); // standard constructor + virtual ~CResetKeyframeValuesDlg(); + + // Dialog Data + enum { IDD = IDD_RESETKEYFRAMEVALUES_DLG }; + +protected: + virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support + + DECLARE_MESSAGE_MAP() + CStatic m_WarningIcon; + +public: + virtual BOOL OnInitDialog(); + CButton m_CancelButton; +}; diff --git a/src/Authoring/Studio/_Win/UI/SceneView.cpp b/src/Authoring/Studio/_Win/UI/SceneView.cpp new file mode 100644 index 00000000..6fcbc6d0 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/SceneView.cpp @@ -0,0 +1,861 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#ifdef _WIN32 +#pragma warning(disable : 4100) // unreferenced formal parameter +#endif +//============================================================================== +// Includes +//============================================================================== +#include "UICOptions.h" +#include "SceneView.h" +//#include "InterpolationDlg.h" +#include "MainFrm.h" +#include "StudioProjectSettings.h" +#include "StudioInstance.h" +#include "StudioPreferences.h" +#include "HotKeys.h" +#include "StudioApp.h" +#include "Doc.h" +#include "Dispatch.h" +#include "MouseCursor.h" +#include "ResourceCache.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "WndControl.h" +#endif +#include "Core.h" +#include "UICDMStudioSystem.h" +#include "IStudioRenderer.h" +#include "ClientDataModelBridge.h" + +#include <QKeyEvent> +#include <QScrollBar> +#include <QSettings> + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== + +CSceneView::CSceneView(CStudioApp *inStudioApp, QWidget *parent) + : QWidget(parent) +{ + Q_UNUSED(inStudioApp) + m_PreviousToolMode = g_StudioApp.GetToolMode(); + m_PreviousSelectMode = g_StudioApp.GetSelectMode(); + + m_PlayerContainerWnd = new CPlayerContainerWnd(this); + connect(m_PlayerContainerWnd, &CPlayerContainerWnd::toolChanged, this, &CSceneView::toolChanged); +#ifdef KDAB_TEMPORARILY_REMOVED + // Create the player container window + CPt theSize = CStudioPreferences::GetDefaultClientSize(); + + // Note that creating with WS_CLIPCHILDREN prevents flickering when SceneView is being + // resized. + m_PlayerContainerWnd->CreateEx(0, AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW), + (HBRUSH)GetStockObject(BLACK_BRUSH)), + L"player_container_wnd", + WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + CRect(0, 0, theSize.x, theSize.y), this, 1000); +#endif + + m_PlayerWnd = new CPlayerWnd(m_PlayerContainerWnd); + connect(m_PlayerWnd, &CPlayerWnd::dropReceived, this, &CSceneView::onDropReceived); +#ifdef KDAB_TEMPORARILY_REMOVED + + // Create the player frame child window + m_PlayerWnd.Create(AfxRegisterWndClass(0, LoadCursor(NULL, IDC_ARROW), + (HBRUSH)GetStockObject(WHITE_BRUSH)), + L"player_wnd", WS_CHILD | WS_VISIBLE, CRect(0, 0, theSize.x, theSize.y), + m_PlayerContainerWnd, 1001); +#endif + m_PlayerContainerWnd->SetPlayerWnd(m_PlayerWnd); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +} + +CSceneView::CSceneView() +{ + m_PreviousToolMode = g_StudioApp.GetToolMode(); + m_PreviousSelectMode = g_StudioApp.GetSelectMode(); +} + +void CSceneView::onDropReceived() +{ + setFocus(); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +CSceneView::~CSceneView() +{ + CDispatch *theDispatch = g_StudioApp.GetCore()->GetDispatch(); + // Stop listening for selection change events + theDispatch->RemoveSelectedNodePropChangeListener(this); + theDispatch->RemoveClientPlayChangeListener(this); +#ifdef INCLUDE_EDIT_CAMERA + theDispatch->RemoveEditCameraChangeListener(this); +#endif +} + +QSize CSceneView::sizeHint() const +{ + CPt theSize = CStudioPreferences::GetDefaultClientSize(); + return QSize(theSize.x, theSize.y); +} + +//====================================================m========================== +/** + * Called by the framework after the view is first attached + * to the document, but before the view is initially displayed. + * Notifies the Main Frame that the palettes need to be shown, and destroys the + * splash screen. + */ +void CSceneView::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + +#ifdef KDAB_TEMPORARILY_REMOVED + + // Modify the style for WS_CLIPCHILDREN + ModifyStyle(0, WS_CLIPCHILDREN); +#endif + + m_PlayerContainerWnd->RecenterClient(); + + // Set the scroll information. + m_PlayerContainerWnd->SetScrollRanges(); + + // Create the cursors + m_ArrowCursor = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ARROW); + m_CursorGroupMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_MOVE); + m_CursorGroupRotate = + CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_ROTATE); + m_CursorGroupScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_GROUP_SCALE); + m_CursorItemMove = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_MOVE); + m_CursorItemRotate = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_ROTATE); + m_CursorItemScale = CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_ITEM_SCALE); + m_CursorEditCameraPan = + CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_PAN); + m_CursorEditCameraRotate = + CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE); + m_CursorEditCameraZoom = + CResourceCache::GetInstance()->GetCursor(CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM); + +#ifdef INCLUDE_EDIT_CAMERA + g_StudioApp.GetCore()->GetDispatch()->AddEditCameraChangeListener(this); +#endif + + // Set the default cursor + OnSetCursor(); +} + +void CSceneView::keyPressEvent(QKeyEvent *event) +{ + /*switch (event->key()) + { + case Qt::Key_Control: + case Qt::Key_Alt: + case Qt::Key_Shift: + case Qt::Key_Meta: + HandleModifierDown(event->key(), event->isAutoRepeat() ? 2 : 1, event->modifiers()); + break; + default: + break; + }*/ +} + +//============================================================================== +/** + * OnToolGroupSelection: Called when the Group Selection button is pressed. + * Sets the current tool mode and changes the cursor. + */ +void CSceneView::OnToolGroupSelection() +{ + m_PreviousSelectMode = g_StudioApp.GetSelectMode(); + g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_GROUP); + OnSetCursor(); + Q_EMIT toolChanged(); +} + +//============================================================================== +/** + * OnToolItemSelection: Called when the Item Selection button is pressed. + * Sets the current tool mode and changes the cursor. + */ +void CSceneView::OnToolItemSelection() +{ + m_PreviousSelectMode = g_StudioApp.GetSelectMode(); + g_StudioApp.SetSelectMode(STUDIO_SELECTMODE_ENTITY); + OnSetCursor(); + Q_EMIT toolChanged(); +} + + +//============================================================================== +/** + * SetViewCursor: Sets the cursor for the view according to the current Client Tool. + * + * Changes the cursor depending on the current tool mode. Each time the Tool mode + * changes, you should call this function. If you add extra tool modes, you + * will need to adjust this function. + */ +void CSceneView::SetViewCursor() +{ + long theCurrentToolSettings = g_StudioApp.GetToolMode(); + long theCurrentSelectSettings = g_StudioApp.GetSelectMode(); + + // See what tool mode we are in + switch (theCurrentToolSettings) { + case STUDIO_TOOLMODE_MOVE: + switch (theCurrentSelectSettings) { + case STUDIO_SELECTMODE_ENTITY: + m_PlayerWnd->setCursor(m_CursorItemMove); + break; + case STUDIO_SELECTMODE_GROUP: + m_PlayerWnd->setCursor(m_CursorGroupMove); + break; + // Default - shouldn't happen + default: + m_PlayerWnd->setCursor(m_CursorItemMove); + break; + } + break; + + case STUDIO_TOOLMODE_ROTATE: + switch (theCurrentSelectSettings) { + case STUDIO_SELECTMODE_ENTITY: + m_PlayerWnd->setCursor(m_CursorItemRotate); + break; + case STUDIO_SELECTMODE_GROUP: + m_PlayerWnd->setCursor(m_CursorGroupRotate); + break; + // Default - shouldn't happen + default: + m_PlayerWnd->setCursor(m_CursorItemRotate); + break; + } + break; + + case STUDIO_TOOLMODE_SCALE: + switch (theCurrentSelectSettings) { + case STUDIO_SELECTMODE_ENTITY: + m_PlayerWnd->setCursor(m_CursorItemScale); + break; + case STUDIO_SELECTMODE_GROUP: + m_PlayerWnd->setCursor(m_CursorGroupScale); + break; + // Default - shouldn't happen + default: + m_PlayerWnd->setCursor(m_CursorItemScale); + break; + } + break; + +#ifdef INCLUDE_EDIT_CAMERA + case STUDIO_TOOLMODE_CAMERA_PAN: + m_PlayerWnd->setCursor(m_CursorEditCameraPan); + break; + + case STUDIO_TOOLMODE_CAMERA_ZOOM: + m_PlayerWnd->setCursor(m_CursorEditCameraZoom); + break; + + case STUDIO_TOOLMODE_CAMERA_ROTATE: + m_PlayerWnd->setCursor(m_CursorEditCameraRotate); + break; +#endif + // Default - shouldn't happen + default: + m_PlayerWnd->setCursor(m_CursorItemMove); + break; + } +} + +//============================================================================== +/** + * RecalcMatte: Recalculates the matte around the Client based on the settings. + * + * This will recalculate the matting around the Client based on the Client's + * current size. If the Client is a "Fit To Window" mode, then the matte region + * is cleared. + */ +//============================================================================== +void CSceneView::RecalcMatte() +{ + long theXOffset = 0; + long theYOffset = 0; + QRect theClientRect = rect(); + + // Adjust the client area based if rulers are visible + if (m_PlayerContainerWnd) { + m_PlayerContainerWnd->setGeometry(theXOffset, theYOffset, + theClientRect.width() - theXOffset, + theClientRect.height() - theYOffset); + + // Recenter the Client rect + m_PlayerContainerWnd->RecenterClient(); + } +} + +//============================================================================== +/** + * PtInClientRect: Returns true if the point lies in the client rect, false otherwise. + * + * @param inPoint The point to check. + */ +//============================================================================== +bool CSceneView::PtInClientRect(const QPoint& inPoint) +{ + return m_PlayerContainerWnd && m_PlayerContainerWnd->geometry().contains(inPoint); +} + +//============================================================================== +/** + * HandleModifierDown: Called when a modifier key (ctrl or alt) is pressed and held. + * + * Changes tool modes and saves the previous mode. + * + * @param inChar Contains the character code value of the key. + * @param inRepCnt Contains the repeat count, the number of times the keystroke + *is repeated when user holds down the key. + * @param inFlags Contains the scan code, key-transition code, previous + *key state, and context code. + */ +//============================================================================== +bool CSceneView::HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers) +{ + bool theHandledFlag = false; + + UNREFERENCED_PARAMETER(inRepCnt); + + // Get the position of the mouse and the rectangle containing the scene view + QPoint theCursorPosition = mapFromGlobal(QCursor::pos()); + QRect theWindowRect = rect(); + + // If we are currently dragging an object or the cursor is over the scene + if (((theWindowRect.contains(theCursorPosition)) + || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) { + bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier; + bool theAltKeyIsDown = modifiers & Qt::AltModifier; + + // If the control key is being pressed and the Alt key is not down + if ((inChar == Qt::Key_Control) && (!theAltKeyIsDown)) { + // If this is the first press, toggle tool modes + m_RegisteredKeyDown = true; + +#ifdef INCLUDE_EDIT_CAMERA + if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) { + // Do nothing, do not let it switch to other tool when middle mouse is down + } else +#endif + { + // See what tool mode we are in and change modes accordingly + SetToolOnCtrl(); + theHandledFlag = true; + } + } + // If the alt key is being pressed and the control key is not down + else if ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown)) { + m_RegisteredKeyDown = true; + +#ifdef INCLUDE_EDIT_CAMERA + if (m_PlayerContainerWnd->IsMiddleMouseDown() && !IsDeploymentView()) { + // press Alt-Scroll Wheel Click + // Do Camera Rotate if we are in 3D Camera + if (g_StudioApp.GetRenderer().DoesEditCameraSupportRotation( + g_StudioApp.GetRenderer().GetEditCamera())) { + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE); + theHandledFlag = true; + } + } else +#endif + { + // See what tool mode we are in and change modes accordingly + SetToolOnAlt(); + theHandledFlag = true; + } + } + OnSetCursor(); + Q_EMIT toolChanged(); + } + + return theHandledFlag; +} + +//============================================================================== +/** + * HandleModifierUp: Handles the release of a modifier key (ctrl or alt). + * + * Changes tool modes back to the original tool mode. + * + * @param inChar Contains the character code value of the key. + * @param inRepCnt Contains the repeat count, the number of times the keystroke is + *repeated when user holds down the key. + * @param inFlags Contains the scan code, key-transition code, previous key + *state, and context code. + */ +//============================================================================== +bool CSceneView::HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers) +{ + UNREFERENCED_PARAMETER(inRepCnt); + + bool theHandledFlag = false; + + // Get the position of the mouse and the rectangle containing the scene view + QPoint theCursorPosition = mapFromGlobal(QCursor::pos()); + QRect theWindowRect = rect(); + + // If we are currently dragging an object or the cursor is over the scene + if (((theWindowRect.contains(theCursorPosition)) + || (m_PlayerContainerWnd && m_PlayerContainerWnd->IsMouseDown()))) { + bool theCtrlKeyIsDown = modifiers & Qt::ControlModifier; + bool theAltKeyIsDown = modifiers & Qt::AltModifier; + + // If the control key or alt key is released (and the opposite key is not down) revert back + // to the original tool mode + if (((inChar == Qt::Key_Control) && (!theAltKeyIsDown)) + || ((inChar == Qt::Key_Alt) && (!theCtrlKeyIsDown))) { +#ifdef INCLUDE_EDIT_CAMERA + if (m_PlayerContainerWnd->IsMiddleMouseDown()) + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + else +#endif + { + RestorePreviousTool(); + } + + OnSetCursor(); + Q_EMIT toolChanged(); + + theHandledFlag = true; + } + // m_RegisteredKeyDown = false; + } + + return theHandledFlag; +} + +//============================================================================== +/** + * resizeEvent: Handles the WM_SIZE message + * + * Recenters the Client and recaluclates the matte when a resize message is + * generated. + * + * @param nType Specifies the type of resizing requested. + * @param cx Specifies the new width of the client area. + * @param cy Specifies the new height of the client area. + */ +//============================================================================== +void CSceneView::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + if (m_PlayerContainerWnd) { + RecalcMatte(); + SetPlayerWndPosition(); + g_StudioApp.GetCore()->GetDoc( )->GetSceneGraph()->RequestRender(); + } +} + +//============================================================================== +/** + * SetPlayerWndPosition: Sets the position of the child player window + * + * Called when the view is scrolled to position the child player window + * + */ +//============================================================================== +void CSceneView::SetPlayerWndPosition() +{ + // Move the child player window to coincide with the scrollbars + if (m_PlayerContainerWnd) { + long theLeft, theTop; + // Retrieve the left and top edge of the presentation currently in view + m_PlayerContainerWnd->SetPlayerWndPosition(theLeft, theTop); + + m_PlayerContainerWnd->update(); + } +} + +//============================================================================== +/** + * GetPlayerHwnd: Gets the window handle for the player object. + * + * @return <HWND> Window handle for the player window + */ +//============================================================================== + +#ifdef KDAB_TEMPORARILY_REMOVED + +HWND CSceneView::GetPlayerHwnd() +{ + HWND thePlayerWnd; + + thePlayerWnd = this->GetSafeHwnd(); + + if (IsWindow(m_PlayerWnd.GetSafeHwnd())) + thePlayerWnd = m_PlayerWnd.GetSafeHwnd(); + + return thePlayerWnd; +} +#endif +//============================================================================== +/** + * SetRegisteredKey: Sets the staus to true or false + * + * If we've already processesed an alt or tab, then set the flag + */ +//============================================================================== +void CSceneView::SetRegisteredKey(bool inStatus) +{ + m_RegisteredKeyDown = inStatus; +} + +//============================================================================== +/** + * GetKeyStatus: get the staus + * + * check to see if the flag is true or false + */ +//============================================================================== +bool CSceneView::GetKeyStatus() +{ + return m_RegisteredKeyDown; +} + +//============================================================================= +/** + * Register all the events for hotkeys that are active for the entire application. + * Hotkeys for the entire application are ones that are not view specific in + * scope. + * + * @param inShortcutHandler the global shortcut handler. + */ +//============================================================================= +void CSceneView::RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler) +{ + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolGroupSelection), 0, Qt::Key_A); + inShortcutHandler->RegisterKeyEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::OnToolItemSelection), 0, Qt::Key_V); + inShortcutHandler->RegisterKeyDownEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown), + Qt::ControlModifier, Qt::Key_Control); + inShortcutHandler->RegisterKeyDownEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierDown), + Qt::AltModifier, Qt::Key_Alt); + inShortcutHandler->RegisterKeyUpEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0, + Qt::Key_Control); + inShortcutHandler->RegisterKeyUpEvent( + new CDynHotKeyConsumer<CSceneView>(this, &CSceneView::HandleModifierUp), 0, + Qt::Key_Alt); +} + +//============================================================================== +/** + * OnSetCursor: Handles the WM_SETCURSOR Windows message. + * + * Changes the cursor depending on the current tool mode. + * + * @param inWnd Specifies a pointer to the window that contains the cursor. + * @param inHitTest Specifies the hit-test area code. The hit test determines the cursor�s + *location. + * @param inMessage Specifies the mouse message number. + * + * @return true if the cursor was set + */ +void CSceneView::OnSetCursor() +{ + SetViewCursor(); +} + +//============================================================================== +/** + * Called when the tool mode changes, scene view maintains its own mode so it can + * return to that mode when modifiers are pressed + * @param inMode the mode to which to change + */ +void CSceneView::SetToolMode(long inMode) +{ + m_PreviousToolMode = inMode; + SetViewCursor(); +} + +//============================================================================== +/** + * Resets its scroll ranges and recenters client in the window. This is called when + * an outside source needs to tell the scene view that size ranges have changed such + * as the preferences telling the sceneview that the size changed. + */ +void CSceneView::RecheckSizingMode() +{ + if (m_PlayerContainerWnd) { + m_PlayerContainerWnd->SetScrollRanges(); + } +} + +//============================================================================= +/** + * Called a selected node property has changed. + * @param inPropertyName name of the property changed + */ +void CSceneView::OnPropValueChanged(const Q3DStudio::CString &inPropertyName) +{ +} + +//============================================================================= +/** + * Called a selected node property has its property changed via a mouse drag + * @param inConstrainXAxis true if dragging is constrained along the X-Axis + * @param inConstrainYAxis true if dragging is constrained along the Y-Axis + */ +void CSceneView::OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis) +{ + // If not constraining to Y-Axis, snap horizontally + // If not constraining to X-Axis, snap vertically + // true to update tranform, as this is called from a mouse drag and the global transform may be + // outdated. + // false to not update the scene, since this is a result of a mouse drag which is already doing + // the updating +} + +//========================================================================== +/** + * Called when the presentation time changes. + * When animating an object, the markers must be updated with the selected object + */ +void CSceneView::OnTimeChanged(long inTime) +{ + UNREFERENCED_PARAMETER(inTime); +} + +//============================================================================== +/** + * Restore to the previous tool mode. This is called when the modifier is released + */ +//============================================================================== +void CSceneView::RestorePreviousTool() +{ + // What was the original tool mode? + switch (m_PreviousToolMode) { + case STUDIO_TOOLMODE_MOVE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE); + break; + + case STUDIO_TOOLMODE_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE); + break; + + case STUDIO_TOOLMODE_SCALE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE); + break; + +#ifdef INCLUDE_EDIT_CAMERA + case STUDIO_TOOLMODE_CAMERA_PAN: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + break; + + case STUDIO_TOOLMODE_CAMERA_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE); + break; + + case STUDIO_TOOLMODE_CAMERA_ZOOM: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM); + break; +#endif + } +} + +//============================================================================== +/** + * Change the tool when the Ctrl Key is pressed + */ +//============================================================================== +void CSceneView::SetToolOnCtrl() +{ + switch (m_PreviousToolMode) { + // If we are in move mode, switch to rotate + case STUDIO_TOOLMODE_MOVE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE); + break; + + // If we are in rotate mode, switch to move + case STUDIO_TOOLMODE_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE); + break; + + // If we are in scale mode, switch to move + case STUDIO_TOOLMODE_SCALE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_MOVE); + break; + +#ifdef INCLUDE_EDIT_CAMERA + // If we are in camera pan mode, switch to camera orbit + case STUDIO_TOOLMODE_CAMERA_PAN: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE); + break; + + // If we are in camera orbit mode, switch to camera pan + case STUDIO_TOOLMODE_CAMERA_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + break; + + // If we are in camera zoom mode, switch to camera pan + case STUDIO_TOOLMODE_CAMERA_ZOOM: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_PAN); + break; +#endif + } +} + +//============================================================================== +/** + * Change the tool when the Alt Key is pressed + */ +//============================================================================== +void CSceneView::SetToolOnAlt() +{ + switch (m_PreviousToolMode) { + // If we are in move mode, switch to rotate + case STUDIO_TOOLMODE_MOVE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE); + break; + + // If we are in rotate mode, switch to move + case STUDIO_TOOLMODE_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_SCALE); + break; + + // If we are in scale mode, switch to move + case STUDIO_TOOLMODE_SCALE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_ROTATE); + break; + +#ifdef INCLUDE_EDIT_CAMERA + // If we are in camera pan mode, switch to camera zoom + case STUDIO_TOOLMODE_CAMERA_PAN: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM); + break; + + // If we are in camera orbit mode, switch to camera zoom + case STUDIO_TOOLMODE_CAMERA_ROTATE: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ZOOM); + break; + + // If we are in camera zoom mode, switch to camera orbit + case STUDIO_TOOLMODE_CAMERA_ZOOM: + g_StudioApp.SetToolMode(STUDIO_TOOLMODE_CAMERA_ROTATE); + break; +#endif + } +} + +//============================================================================== +/** + * Redirect to PlayerContainerWnd to check whether we are in deployment view mode. + * @return true if is in deployment view mode, else false + */ +bool CSceneView::IsDeploymentView() +{ + // default mode is SCENE_VIEW so if playercontainerwnd does not exist ( should only happen on + // startup ), + // it is deployment view + bool theStatus = true; + if (m_PlayerContainerWnd) + theStatus = m_PlayerContainerWnd->IsDeploymentView(); + + return theStatus; +} + +//============================================================================== +/** + * Redirect to PlayerContainerWnd to set the view mode of the current scene view, + * whether we are in editing mode or deployment mode. For editing mode, we want to + * use the full scene area without any matte area. + * @param inViewMode the view mode of this scene + */ +void CSceneView::SetViewMode(CPlayerContainerWnd::EViewMode inViewMode) +{ + if (m_PlayerContainerWnd) { + m_PlayerContainerWnd->SetViewMode(inViewMode); + } +} + +//============================================================================== +/** + * When the active camera is changed, the display string needs to be changed. Hence + * find which entry is the one which is modified and update with the new string + * @param inCamera the camera that has been modified + */ +void CSceneView::OnEditCameraChanged() +{ + // reset any scrolling and recalculate the window position. + if (m_PlayerContainerWnd) { + m_PlayerContainerWnd->SetScrollRanges(); + RecalcMatte(); + SetPlayerWndPosition(); + } + + // update the view mode accordingly + SetViewMode(g_StudioApp.GetRenderer().GetEditCamera() >= 0 ? CPlayerContainerWnd::VIEW_EDIT + : CPlayerContainerWnd::VIEW_SCENE); + // redraw the scene so that markers can be calculated correctly + // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false ); + m_PlayerWnd->update(); +} + +//============================================================================== +/** + * When the active camera is changed, the display string needs to be changed. Hence + * find which entry is the one which is modified and update with the new string + * @param inCamera the camera that has been modified + */ +void CSceneView::OnEditCamerasTransformed() +{ +} + +void CSceneView::OnAuthorZoomChanged() +{ + OnEditCameraChanged(); +} + +void CSceneView::OnRulerGuideToggled() +{ + m_PlayerContainerWnd->OnRulerGuideToggled(); +} diff --git a/src/Authoring/Studio/_Win/UI/SceneView.h b/src/Authoring/Studio/_Win/UI/SceneView.h new file mode 100644 index 00000000..12a58c6a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/SceneView.h @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_SCENE_VIEW_H +#define INCLUDED_SCENE_VIEW_H 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +#include <QWidget> +#include <QCursor> + +#include "EditorPane.h" +#include "PlayerWnd.h" +#include "PlayerContainerWnd.h" +#include "DispatchListeners.h" + +class CStudioApp; +class CHotKeys; +class CMouseCursor; +class CWndControl; + +//============================================================================== +// Forwards +//============================================================================== + +//============================================================================== +// Class CSceneView +//============================================================================== + +//============================================================================== +/** + * CSceneView: Scene View. + * + * Provides the view of the scene and displays the 3D Client window. + */ +//============================================================================== +class CSceneView : public QWidget, + public CEditorPane, + public CSelectedNodePropChangeListener, + public CClientPlayChangeListener, + public CEditCameraChangeListener +{ + Q_OBJECT + //========================================================================== + // Protected Properties + //========================================================================== +protected: + bool m_FitClientToWindow = false; ///< True if user selected fit to window in prefrences + bool m_RegisteredKeyDown = false; ///< True if a key is down + CPlayerContainerWnd *m_PlayerContainerWnd = nullptr; ///< first-level child + CPlayerWnd *m_PlayerWnd = nullptr; ///< second-level child (grandchild) + QCursor m_ArrowCursor; ///< A pointer to the current cursor (changes according to mode) + QCursor m_CursorGroupMove; ///< The move group cursor + QCursor m_CursorGroupRotate; ///< The rotate group cursor + QCursor m_CursorGroupScale; ///< The scale group cursor + QCursor m_CursorItemMove; ///< The move item cursor + QCursor m_CursorItemRotate; ///< The rotate item cursor + QCursor m_CursorItemScale; ///< The scale item cursor + QCursor m_CursorEditCameraPan; ///< The edit camera pan cursor + QCursor m_CursorEditCameraRotate; ///< The edit camera rotate cursor + QCursor m_CursorEditCameraZoom; ///< The edit camera zoom cursor + + long m_PreviousToolMode; ///< The previous tool mode (used when toggling with hotkeys to switch + ///back to previous mode on release) + long m_PreviousSelectMode; ///< The previous select mode + + //========================================================================== + // Protected Methods + //========================================================================== +protected: // create from serialization only + + //========================================================================== + // Public Methods + //========================================================================== +public: + CSceneView(CStudioApp *inStudioApp, QWidget *parent = nullptr); + CSceneView(); // used for serialization only! + virtual ~CSceneView(); + + bool HandleModifierUp(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers); + bool HandleModifierDown(int inChar, int inRepCnt, Qt::KeyboardModifiers modifiers); + bool PtInClientRect(const QPoint& inPoint); + void SetViewCursor(); + void SetToolMode(long inMode); + void RecheckSizingMode(); + + void SetRegisteredKey(bool inStatus); + void RegisterGlobalKeyboardShortcuts(CHotKeys *inShortcutHandler); + bool GetKeyStatus(); + + void SetPlayerWndPosition(); + + // redirect to/from PlayerContainerWnd + bool IsDeploymentView(); + void SetViewMode(CPlayerContainerWnd::EViewMode inViewMode); + + // Tool helper methods + void RestorePreviousTool(); + void SetToolOnCtrl(); + void SetToolOnAlt(); + + void OnRulerGuideToggled(); + + // CSelectedNodePropChangeListener + void OnPropValueChanged(const Q3DStudio::CString &inPropertyName) override; + void OnMouseDragged(bool inConstrainXAxis, bool inConstrainYAxis) override; + + // CClientPlayChangeListener + void OnTimeChanged(long inTime) override; + + // CEditCameraChangeListener + + void OnEditCameraChanged() override; + void OnEditCamerasTransformed() override; + void OnAuthorZoomChanged() override; + + QSize sizeHint() const override; + + void OnToolGroupSelection(); + void OnToolItemSelection(); +public: + + void resizeEvent(QResizeEvent *event) override; + +Q_SIGNALS: + void toolChanged(); + +protected: + void RecalcMatte(); + + // Generated message map functions +protected: + void OnSetCursor(); + void showEvent(QShowEvent *event) override; + void keyPressEvent(QKeyEvent *event) override; +private: + void onDropReceived(); +}; + +///////////////////////////////////////////////////////////////////////////// + +#endif // INCLUDED_SCENE_VIEW_H diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.cpp b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp new file mode 100644 index 00000000..286d94e3 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StartupDlg.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "StudioDefs.h" +#include "Strings.h" +#include "StringLoader.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "StartupDlg.h" + +#include "StudioPreferences.h" +#include "ui_StartupDlg.h" + +#include <QtCore/qfileinfo.h> +#include <QtGui/qpalette.h> +#include <QtCore/qdatetime.h> +#include <QtCore/qdir.h> + +// CStartupDlg dialog + +CStartupDlg::CStartupDlg(QWidget *pParent) + : QDialog(pParent, Qt::MSWindowsFixedSizeDialogHint | Qt::FramelessWindowHint) + , m_Choice(EStartupChoice_Invalid) + , m_RecentDocSelected("") + , m_ui(new Ui::StartupDlg) + , m_palette(nullptr) +{ + m_ui->setupUi(this); +} + +CStartupDlg::~CStartupDlg() +{ + delete m_palette; +} + +static QString GetFileTimeReadable(const CUICFile &inFile) +{ + QFileInfo finfo(inFile.GetAbsolutePath().toQString()); + if (!finfo.exists()) + return {}; + + return finfo.lastModified().toString("MM/dd/yyyy"); +} + +void CStartupDlg::showEvent(QShowEvent *ev) +{ + OnInitDialog(); + QDialog::showEvent(ev); +} + +void CStartupDlg::OnInitDialog() +{ + connect(m_ui->newDocument, &QPushButton::clicked, this, &CStartupDlg::OnNewDocClicked); + connect(m_ui->openDocument, &QPushButton::clicked, this, &CStartupDlg::OnOpenDocClicked); + + // Load the product version + m_ProductVersionStr.Format( + ::LoadResourceString(IDS_UIC_STUDIO_VERSION), + static_cast<const wchar_t *>(CStudioPreferences::GetVersionString())); + m_ui->versionStr->setText(m_ProductVersionStr.toQString()); + + // Populate the recent document list + for (uint theIndex = 0; theIndex < RECENT_COUNT; ++theIndex) { + ClickableLabel *recent + = findChild<ClickableLabel *>(QStringLiteral("recent%1").arg(theIndex)); + connect(recent, &ClickableLabel::clicked, this, &CStartupDlg::OnStnClickedStartupRecent); + + recent->setProperty("recentIndex", theIndex); + + if (m_RecentDocs.size() > theIndex) { + // Set the name + recent->setText(m_RecentDocs[theIndex].GetName().toQString()); + // Set path and date to tooltip + QFileInfo thePath(m_RecentDocs[theIndex].GetAbsolutePath().toQString()); + QString toolTip = thePath.absoluteDir().path(); + toolTip.append(QStringLiteral("\n")); + toolTip.append(GetFileTimeReadable(m_RecentDocs[theIndex])); + recent->setToolTip(toolTip); + } else { + recent->hide(); + } + } +} + +void CStartupDlg::AddRecentItem(const CUICFile &inRecentItem) +{ + m_RecentDocs.push_back(inRecentItem); +} + +CStartupDlg::EStartupChoice CStartupDlg::GetChoice() +{ + return m_Choice; +} + +CUICFile CStartupDlg::GetRecentDoc() const +{ + return m_RecentDocSelected; +} + +void CStartupDlg::OnNewDocClicked() +{ + m_Choice = EStartupChoice_NewDoc; + QDialog::accept(); +} + +void CStartupDlg::OnOpenDocClicked() +{ + m_Choice = EStartupChoice_OpenDoc; + QDialog::accept(); +} + +void CStartupDlg::OnStnClickedStartupRecent() +{ + const int index = sender()->property("recentIndex").toInt(); + OpenRecent(index); +} + +void CStartupDlg::OpenRecent(size_t inIndex) +{ + if (inIndex < m_RecentDocs.size()) { + m_RecentDocSelected = m_RecentDocs[inIndex]; + m_Choice = EStartupChoice_OpenRecent; + QDialog::accept(); + } +} + +void CStartupDlg::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + if (m_palette) + return; + + delete m_palette; + m_palette = new QPalette; + QPixmap pic = QPixmap(":/startup/open_dialog.png"); + pic.setDevicePixelRatio(devicePixelRatio()); + m_palette->setBrush(QPalette::Window, pic); + setPalette(*m_palette); + resize(pic.size()); + setFixedSize(size()); +} diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.h b/src/Authoring/Studio/_Win/UI/StartupDlg.h new file mode 100644 index 00000000..6fbd0a2a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StartupDlg.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2006 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#ifndef INCLUDED_STARTUP_DLG +#define INCLUDED_STARTUP_DLG 1 + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +#include <QDialog> + +#include "UICString.h" +#include "UICFile.h" + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { + class StartupDlg; +} +QT_END_NAMESPACE + +//============================================================================== +/** + * CGLVersionDlg: Dialog class for showing what user can do upon startup + */ +//============================================================================== +class CStartupDlg : public QDialog +{ + Q_OBJECT +public: + enum EStartupChoice { + EStartupChoice_Invalid = -1, + EStartupChoice_NewDoc, + EStartupChoice_OpenDoc, + EStartupChoice_OpenRecent, + EStartupChoice_Exit + }; + +public: + CStartupDlg(QWidget *pParent = nullptr); // standard constructor + virtual ~CStartupDlg(); + +protected: + const static int RECENT_COUNT = 5; + + void paintEvent(QPaintEvent *event) override; + void showEvent(QShowEvent *) override; + +protected Q_SLOTS: + void OnNewDocClicked(); + void OnOpenDocClicked(); + void OnStnClickedStartupRecent(); + void OpenRecent(size_t inIndex); + +private: + // Dialog background + QPalette *m_palette; + + // Product version string + Q3DStudio::CString m_ProductVersionStr; + + // Choice + EStartupChoice m_Choice = EStartupChoice_Invalid; + + // Recent Docs + std::vector<CUICFile> m_RecentDocs; + CUICFile m_RecentDocSelected; + +public: + void OnInitDialog(); + void AddRecentItem(const CUICFile &inRecentItem); + EStartupChoice GetChoice(); + CUICFile GetRecentDoc() const; + +private: + QScopedPointer<Ui::StartupDlg> m_ui; +}; + +#endif // INCLUDED_STARTUP_DLG diff --git a/src/Authoring/Studio/_Win/UI/StartupDlg.ui b/src/Authoring/Studio/_Win/UI/StartupDlg.ui new file mode 100644 index 00000000..619c857a --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StartupDlg.ui @@ -0,0 +1,171 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StartupDlg</class> + <widget class="QDialog" name="StartupDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>442</width> + <height>650</height> + </rect> + </property> + <widget class="QLabel" name="recentDocLabel"> + <property name="geometry"> + <rect> + <x>20</x> + <y>250</y> + <width>411</width> + <height>29</height> + </rect> + </property> + <property name="text"> + <string>RECENT FILES</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + </widget> + <widget class="QWidget" name="verticalLayoutWidget"> + <property name="geometry"> + <rect> + <x>30</x> + <y>290</y> + <width>401</width> + <height>341</height> + </rect> + </property> + <layout class="QVBoxLayout" name="recentList"> + <item> + <widget class="ClickableLabel" name="recent0"> + <property name="text"> + <string>Recent0.uip</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="docIndex" stdset="0"> + <number>0</number> + </property> + </widget> + </item> + <item> + <widget class="ClickableLabel" name="recent1"> + <property name="text"> + <string>Recent1.uip</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="docIndex" stdset="0"> + <number>1</number> + </property> + </widget> + </item> + <item> + <widget class="ClickableLabel" name="recent2"> + <property name="text"> + <string>Recent2.uip</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="docIndex" stdset="0"> + <number>2</number> + </property> + </widget> + </item> + <item> + <widget class="ClickableLabel" name="recent3"> + <property name="text"> + <string>Recent3.uip</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="docIndex" stdset="0"> + <number>3</number> + </property> + </widget> + </item> + <item> + <widget class="ClickableLabel" name="recent4"> + <property name="text"> + <string>Recent3.uip</string> + </property> + <property name="alignment"> + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> + </property> + <property name="docIndex" stdset="0"> + <number>3</number> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QWidget" name="verticalLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>130</y> + <width>161</width> + <height>101</height> + </rect> + </property> + <layout class="QVBoxLayout" name="buttons"> + <item> + <widget class="QPushButton" name="newDocument"> + <property name="text"> + <string>Create Project...</string> + </property> + <property name="icon"> + <iconset resource="../../MainFrm.qrc"> + <normaloff>:/res/Toolbar-00.png</normaloff>:/res/Toolbar-00.png</iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="openDocument"> + <property name="text"> + <string>Open Project...</string> + </property> + <property name="icon"> + <iconset resource="../../MainFrm.qrc"> + <normaloff>:/res/Toolbar-01.png</normaloff>:/res/Toolbar-01.png</iconset> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="versionStr"> + <property name="geometry"> + <rect> + <x>290</x> + <y>90</y> + <width>141</width> + <height>20</height> + </rect> + </property> + <property name="text"> + <string>Qt 3D Studio version string</string> + </property> + </widget> + </widget> + <customwidgets> + <customwidget> + <class>ClickableLabel</class> + <extends>QLabel</extends> + <header>ClickableLabel.h</header> + </customwidget> + </customwidgets> + <resources> + <include location="../../MainFrm.qrc"/> + </resources> + <connections/> +</ui> diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp new file mode 100644 index 00000000..bde792eb --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.cpp @@ -0,0 +1,590 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#include "Strings.h" + +#include "ui_StudioAppPrefsPage.h" + +//============================================================================== +// Includes +//============================================================================== +#include "UICOptions.h" +#include "Doc.h" +#include "StudioAppPrefsPage.h" +#include "StudioConst.h" +#include "StudioProjectSettings.h" +#include "StudioPreferences.h" +#include "StudioApp.h" +#include "StudioPreferences.h" +#include "StringLoader.h" +#include "CommonConstants.h" +#include "Views.h" +#include "UICDMStudioSystem.h" +#include "ClientDataModelBridge.h" +#include "Core.h" +#include "IStudioRenderer.h" + +#include <QColorDialog> +#include <QMessageBox> + +#define WM_PREVIEW_DYNAMIC_CONTROLS WM_USER + 1200 +const long MIN_PAGESIZE = 380; + +///////////////////////////////////////////////////////////////////////////// +// CStudioAppPrefsPage property page + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CStudioAppPrefsPage::CStudioAppPrefsPage(QWidget *parent) + : CStudioPreferencesPropPage(parent) + , m_nudgeValue(0.0) + , m_TimebarShowTime(FALSE) + , m_InterpolationIsSmooth(FALSE) + , m_ui(new Ui::StudioAppPrefsPage) +{ + m_Font = QFont(CStudioPreferences::GetFontFaceName()); + m_Font.setPixelSize(CStudioPreferences::fontSize()); + + // Create a bold font for the group box text + m_BoldFont = m_Font; + m_BoldFont.setBold(true); + + OnInitDialog(); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CStudioAppPrefsPage::~CStudioAppPrefsPage() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CStudioAppPrefsPage message handlers + +void CStudioAppPrefsPage::OnInitDialog() +{ + m_ui->setupUi(this); + m_ui->m_editNudgeAmount->setValidator(new QDoubleValidator(this)); + + // Add tool tips for controls + m_ui->m_editNudgeAmount->setToolTip(::LoadResourceString(IDS_PREFS_NUDGEAMOUNT).toQString()); + m_ui->m_DefaultInterpolation->setToolTip(::LoadResourceString(IDS_PREFS_INTERPOLATIONDEFAULT).toQString()); + m_ui->m_checkTimelineAbsoluteSnapping->setToolTip( + ::LoadResourceString(IDS_PREFS_TIMELINEGRIDSNAPPING).toQString()); + m_ui->m_SnapRangeCombo->setToolTip(::LoadResourceString(IDS_PREFS_TIMELINEGRIDRESOLUTION).toQString()); + m_ui->m_buttonRestoreDefaults->setToolTip(::LoadResourceString(IDS_PREFS_RESTOREDEFAULTS).toQString()); + m_ui->m_EditViewBGColor->setAutoFillBackground(true); + + // Set fonts for child windows. + for (auto w : findChildren<QWidget *>()) + w->setFont(m_Font); + + // Make the group text bold + for (auto w : findChildren<QGroupBox *>()) + w->setFont(m_BoldFont); + +#ifndef INCLUDE_EDIT_CAMERA + ASSERT(0); + // This won't work as all the controls have to move accordingly. Don't think INCLUDE_EDIT_CAMERA + // will be undefined + // Hide controls related to Edit Camera + m_ui->m_groupBoxEditingView->setVisible(false); +#endif + + // Load the settings for the controls + LoadSettings(); + + auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated); + connect(m_ui->m_buttonRestoreDefaults, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnButtonRestoreDefaults); + connect(m_ui->m_DefaultInterpolation, activated, this, &CStudioAppPrefsPage::OnSelChangeInterpolationDefault); + connect(m_ui->m_SnapRangeCombo, activated, this, &CStudioAppPrefsPage::OnSelChangeSnapRange); + connect(m_ui->m_checkTimelineAbsoluteSnapping, &QCheckBox::clicked, this, &CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping); + connect(m_ui->m_EditViewBGColor, &QPushButton::clicked, this, &CStudioAppPrefsPage::OnBgColorButtonClicked); + connect(m_ui->m_editNudgeAmount, &QLineEdit::textEdited, this, &CStudioAppPrefsPage::OnChangeEditNudgeAmount); + connect(m_ui->m_EditViewStartupView, activated, this, &CStudioAppPrefsPage::OnSelChangeStartupView); + connect(m_ui->m_PreviewSelector, activated, this, &CStudioAppPrefsPage::OnChangePreviewConfiguration); +} + +//============================================================================== +/** + * LoadSettings: Load the settings from the CDoc and set the control values. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::LoadSettings() +{ + m_nudgeValue = CStudioPreferences::GetNudgeAmount(); + + // Get the Interpolation Preference + Q3DStudio::CString theComboItem; + theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_1); + m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString()); + theComboItem = ::LoadResourceString(IDS_PREF_INTERPOLATION_2); + m_ui->m_DefaultInterpolation->addItem(theComboItem.toQString()); + + long theInterpolationPref = 0; + if (CStudioPreferences::GetInterpolation()) + theInterpolationPref = 0; + else + theInterpolationPref = 1; + m_ui->m_DefaultInterpolation->setCurrentIndex(theInterpolationPref); + + // Timeline snapping grid + m_ui->m_checkTimelineAbsoluteSnapping->setChecked( + CStudioPreferences::IsTimelineSnappingGridActive()); + + // Load the combo boxes with values from the string table so that they are localizable. + // The scale mode + (void)theComboItem; + theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_1); + m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString()); + theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_2); + m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString()); + theComboItem = ::LoadResourceString(IDS_PREF_SNAPRANGE_3); + m_ui->m_SnapRangeCombo->addItem(theComboItem.toQString()); + long theResolution = (long)CStudioPreferences::GetTimelineSnappingGridResolution(); + m_ui->m_SnapRangeCombo->setCurrentIndex(theResolution); + +#ifdef INCLUDE_EDIT_CAMERA + // Edit View Background color + // TODO: Visualize selected color on the bg color change button + InitEditStartViewCombo(); +#endif + + EnableOptions(); + + LoadPreviewSelections(); + + m_ui->m_editNudgeAmount->setText(QString::number(m_nudgeValue)); + m_bgColor = CStudioPreferences::GetEditViewBackgroundColor(); + updateColorButton(); +} + +void CStudioAppPrefsPage::updateColorButton() +{ + QPalette pal = m_ui->m_EditViewBGColor->palette(); + pal.setColor(QPalette::Button, m_bgColor); + m_ui->m_EditViewBGColor->setPalette(pal); +} + +//============================================================================== +/** + * SaveSettings: Save the settings from the controls to the CDoc + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::SaveSettings() +{ + // Nudge amount + CStudioPreferences::SetNudgeAmount(m_nudgeValue); + + // Default interpolation + g_StudioApp.GetCore()->GetDoc()->SetDefaultKeyframeInterpolation( + m_ui->m_DefaultInterpolation->currentIndex() == 0); + + // Timeline snapping grid + CStudioPreferences::SetTimelineSnappingGridActive( + m_ui->m_checkTimelineAbsoluteSnapping->isChecked()); + long theCurrentSelection = m_ui->m_SnapRangeCombo->currentIndex(); + CStudioPreferences::SetTimelineSnappingGridResolution((ESnapGridResolution)theCurrentSelection); + +#ifdef INCLUDE_EDIT_CAMERA + // Edit View Background Color + CStudioPreferences::SetEditViewBackgroundColor(m_bgColor); + // + // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theColor ); + + // Preferred Startup View + long theSel = m_ui->m_EditViewStartupView->currentIndex(); + long theNumItems = m_ui->m_EditViewStartupView->count(); + CStudioPreferences::SetPreferredStartupView( + (theSel == theNumItems - 1) ? -1 : theSel); // -1 for deployment view +// g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false ); +#endif + + SavePreviewSettings(); +} + +//============================================================================== +/** + * OnApply: Handler for the Apply button + * + * @param None + */ +//============================================================================== +bool CStudioAppPrefsPage::OnApply() +{ + // Apply was clicked - save settings and disabled the Apply button + this->SaveSettings(); + + this->SetModified(FALSE); + + // Request that the renderer refreshes as settings may have changed + g_StudioApp.GetRenderer().RequestRender(); + + return CStudioPreferencesPropPage::OnApply(); +} + +//============================================================================== +/** + * OnOK: Handler for the OK button + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnOK() +{ + CStudioPreferencesPropPage::OnOK(); +} + +//============================================================================== +/** + * OnCancel: Handler for the Cancel button + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnCancel() +{ +#ifdef INCLUDE_EDIT_CAMERA + // if the edit view background color was changed, reset it back to the original + // value + CColor theOrigColor = CStudioPreferences::GetEditViewBackgroundColor(); + if (m_bgColor != theOrigColor) { + // g_StudioApp.GetCore()->GetDoc( )->SetEditViewBackgroundColor( theOrigColor ); + // g_StudioApp.GetCore()->GetDoc( )->UpdateClientScene( false ); + } +#endif + CStudioPreferencesPropPage::OnCancel(); +} + +//============================================================================== +/** + * OnButtonRestoreDefaults: Restore the defaults and exit the preferences. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnButtonRestoreDefaults() +{ + Q3DStudio::CString theMessage; + Q3DStudio::CString theTitle; + int theChoice = 0; + + // Load the text strings for the message box + theTitle = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TITLE); + theMessage = ::LoadResourceString(IDS_PREF_RESTOREDEFAULT_TEXT); + + // Ask the user if she really wants to do this + theChoice = QMessageBox::question(this, theTitle.toQString(), theMessage.toQString()); + + // If the "yes" button was selected + if (theChoice == QMessageBox::Yes) { + // Restore default preferences by passing PREFS_RESET_DEFAULTS back + // to the CStudioDocPreferences (that called this preferences sheet) + CStudioPreferencesPropPage::EndDialog(PREFS_RESET_DEFAULTS); + } +} + +//============================================================================== +/** + * OnSelChangeInterpolationDefault: CBN_SELCHANGE handler for the + * IDC_INTERPOLATION_DEFAULT combo + *box. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnSelChangeInterpolationDefault() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeEditNudgeAmount: EN_UPDATE handler for the IDC_EDIT_NUDGE + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnChangeEditNudgeAmount() +{ + QString editStr = m_ui->m_editNudgeAmount->text(); + m_nudgeValue = editStr.toDouble(); + this->SetModified(true); +} + +//============================================================================== +/** + * OnSelChangeSnapRange: CBN_SELCHANGE handler for the IDC_SNAPRANGE combo box. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnSelChangeSnapRange() +{ + this->SetModified(true); +} + +//============================================================================== +/** + * OnCheckTimelineAbsoluteSnapping: Handler for the IDC_CHECK_TIMELINEABSOLUTESNAPPING + *checkbox. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::OnCheckTimelineAbsoluteSnapping() +{ + this->SetModified(true); + this->EnableOptions(); +} + +//============================================================================== +/** + * EnableOptions: Enable/disable options. + * + * @param None + */ +//============================================================================== +void CStudioAppPrefsPage::EnableOptions() +{ + m_ui->m_SnapRangeCombo->setEnabled(m_ui->m_checkTimelineAbsoluteSnapping->isChecked()); +} + +//============================================================================== +/** + * OnSelChangeStartupView: CBN_SELCHANGE handler for the IDC_COMBO_EDIT_STARTUP_VIEW + * Combo box + */ +void CStudioAppPrefsPage::OnSelChangeStartupView() +{ + this->SetModified(true); +} + +//============================================================================== +/** + * Initialise the combo box that displays the preferred startup view. + * Set the initial selection to that saved to the preferences + */ +//============================================================================== +void CStudioAppPrefsPage::InitEditStartViewCombo() +{ + Q3DStudio::IStudioRenderer &theRenderer = g_StudioApp.GetRenderer(); + QStringList theCameraNames; + theRenderer.GetEditCameraList(theCameraNames); + for (size_t idx = 0, end = theCameraNames.size(); idx < end; ++idx) { + m_ui->m_EditViewStartupView->addItem( + theCameraNames.at(idx)); + m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, QVariant((int)idx + 1)); + } + + m_ui->m_EditViewStartupView->addItem("--------------------------"); + m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, -1); // set to an invalid pointer + // add the deployment view as the last selection + m_ui->m_EditViewStartupView->addItem(::LoadResourceString(IDS_SCENE_CAMERA_VIEW).toQString()); + m_ui->m_EditViewStartupView->setItemData(m_ui->m_EditViewStartupView->count() - 1, 0); + + long thePreferredView = CStudioPreferences::GetPreferredStartupView(); + long theNumItems = m_ui->m_EditViewStartupView->count(); + if (thePreferredView == -1) // deployment view + m_ui->m_EditViewStartupView->setCurrentIndex(theNumItems - 1); // set to the last one + else if (thePreferredView < theNumItems - 1) + m_ui->m_EditViewStartupView->setCurrentIndex(thePreferredView); + else // possibly from old content where cameras are removed + m_ui->m_EditViewStartupView->setCurrentIndex(0); +} + +void CStudioAppPrefsPage::LoadPreviewSelections() +{ + // Load the configurations from all the .build files + Q3DStudio::CBuildConfigurations &theConfig = g_StudioApp.GetCore()->GetBuildConfigurations(); + Q3DStudio::CBuildConfigurations::TBuildConfigurations theConfigurations = + theConfig.GetConfigurations(); + Q3DStudio::CBuildConfigurations::TBuildConfigurations::iterator theIter; + for (theIter = theConfigurations.begin(); theIter != theConfigurations.end(); ++theIter) { + const Q3DStudio::CString &theConfig = theIter->first; + m_ui->m_PreviewSelector->addItem(theConfig.toQString()); + m_ui->m_PreviewSelector->setItemData(m_ui->m_PreviewSelector->count() - 1, + QVariant::fromValue(theIter->second)); + } + + int thePreviewSelected = m_ui->m_PreviewSelector->findText(CStudioPreferences::GetPreviewConfig().toQString()); + m_ui->m_PreviewSelector->setCurrentIndex(thePreviewSelected); + if (thePreviewSelected == -1) { + // select the first build configuration, or if no conriguration, the first application, i.e. + // AMPlayer + m_ui->m_PreviewSelector->setCurrentIndex(0); + long thePreviewCount = m_ui->m_PreviewSelector->count(); + for (long theIndex = 0; theIndex < thePreviewCount; ++theIndex) { + if (m_ui->m_PreviewSelector->itemData(theIndex).value<Q3DStudio::CBuildConfiguration *>() != nullptr) { + m_ui->m_PreviewSelector->setCurrentIndex(theIndex); + break; + } + } + } + + LoadBuildProperties(); +} + +//============================================================================== +/** + * When the build configuration is changed, all the properties have to be updated. + */ +//============================================================================== +void CStudioAppPrefsPage::OnChangePreviewConfiguration() +{ + LoadBuildProperties(); +} + +void CStudioAppPrefsPage::OnBgColorButtonClicked() +{ + QColorDialog dlg(this); + dlg.setCurrentColor(m_bgColor); + if (dlg.exec() == QDialog::Accepted) { + m_bgColor = dlg.selectedColor(); + updateColorButton(); + } + + this->SetModified(true); +} + +//============================================================================== +/** + * Load the build properties for the current preview application selected + */ +//============================================================================== +void CStudioAppPrefsPage::LoadBuildProperties() +{ + // Remove those dynamic controls + RemovePreviewPropertyControls(); + + if (m_ui->m_PreviewSelector->count() > 0) { + Q3DStudio::CBuildConfiguration *theConfig = + m_ui->m_PreviewSelector->itemData(m_ui->m_PreviewSelector->currentIndex()).value<Q3DStudio::CBuildConfiguration *>(); + if (theConfig) { + // Only configuration read from .build files will have the ItemDataPtr set. + + Q3DStudio::CBuildConfiguration::TConfigProperties &theProperties = + theConfig->GetBuildProperties(); + + auto layout = qobject_cast<QFormLayout *>(m_ui->groupBoxPreview->layout()); + auto activated = static_cast<void(QComboBox::*)(int)>(&QComboBox::activated); + + if (theProperties.empty() == false) { + Q3DStudio::CBuildConfiguration::TConfigProperties::iterator theIter; + + for (theIter = theProperties.begin(); theIter != theProperties.end(); ++theIter) { + Q3DStudio::CBuildConfiguration::TConfigPropertyValues &theValues = + theIter->GetAcceptableValues(); + // Only create the combo if there is more than 1 choices + if (theValues.size() > 1) { + Q3DStudio::CBuildConfiguration::TConfigPropertyValues::iterator + theValueIter; + long theMaxLength = 0; + for (theValueIter = theValues.begin(); theValueIter != theValues.end(); + ++theValueIter) { + long theLabelLength = theValueIter->GetLabel().Length(); + if (theLabelLength > theMaxLength) + theMaxLength = theLabelLength; + } + + QLabel *theStaticText = new QLabel(theIter->GetLabel().toQString()); + theStaticText->setFont(m_Font); + QComboBox *thePropertyDropdown = new QComboBox(); + connect(thePropertyDropdown, activated, [&]() {SetModified(true);}); + thePropertyDropdown->setFont(m_Font); + layout->addRow(theStaticText, thePropertyDropdown); + + m_BuildProperties.push_back(std::make_pair( + &*theIter, std::make_pair(theStaticText, thePropertyDropdown))); + + Q3DStudio::CString thePropertyValue = + CStudioPreferences::GetPreviewProperty(theIter->GetName()); + for (theValueIter = theValues.begin(); theValueIter != theValues.end(); + ++theValueIter) { + thePropertyDropdown->addItem(theValueIter->GetLabel().toQString()); + thePropertyDropdown->setItemData(thePropertyDropdown->count() - 1, QVariant::fromValue(&*theValueIter)); + if (theValueIter->GetName() == thePropertyValue) + thePropertyDropdown->setCurrentIndex(thePropertyDropdown->count() - 1); + } + + // Select the first entry + if (thePropertyDropdown->currentIndex() == -1) + thePropertyDropdown->setCurrentIndex(0); + } + } + } + } + } +} + +void CStudioAppPrefsPage::SavePreviewSettings() +{ + QString thePreviewApp = m_ui->m_PreviewSelector->currentText(); + CStudioPreferences::SetPreviewConfig(Q3DStudio::CString::fromQString(thePreviewApp)); + + std::list<TBuildNameControlPair>::iterator theIter; + for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) { + QComboBox *theCombo = theIter->second.second; + Q3DStudio::CString theName = theIter->first->GetName(); + Q3DStudio::CBuildConfiguration::SConfigPropertyValue *thePropertyValue = + theCombo->itemData(theCombo->currentIndex()).value<Q3DStudio::CBuildConfiguration::SConfigPropertyValue *>(); + CStudioPreferences::SetPreviewProperty(theName, thePropertyValue->GetName()); + } +} + +//============================================================================== +/** + * Remove all the dynamically added controls that was read in from the build file + */ +//============================================================================== +void CStudioAppPrefsPage::RemovePreviewPropertyControls() +{ + // Remove the created control + std::list<TBuildNameControlPair>::iterator theIter; + for (theIter = m_BuildProperties.begin(); theIter != m_BuildProperties.end(); ++theIter) { + delete theIter->second.first; + delete theIter->second.second; + } + m_BuildProperties.clear(); +} diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h new file mode 100644 index 00000000..a3be36c2 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_) +#define AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//============================================================================== +// Includes +//============================================================================== +#include "BuildConfigParser.h" + +#include "StudioPreferencesPropSheet.h" + +class QComboBox; +class QLabel; + +class CStudioApp; +///////////////////////////////////////////////////////////////////////////// +// CStudioAppPrefsPage dialog + +namespace Ui +{ + class StudioAppPrefsPage; +} + +class CStudioAppPrefsPage : public CStudioPreferencesPropPage +{ + Q_OBJECT +protected: + typedef std::pair<QLabel *, QComboBox *> TBuildLabelDropdownPair; + typedef std::pair<Q3DStudio::CBuildConfiguration::SConfigProperty *, TBuildLabelDropdownPair> + TBuildNameControlPair; + + // Construction +public: + explicit CStudioAppPrefsPage(QWidget *parent = nullptr); + ~CStudioAppPrefsPage(); + + // Dialog Data + QColor m_bgColor; + + double m_nudgeValue; + +public: + bool OnApply() override; + void OnOK() override; + void OnCancel() override; + + // Implementation +protected: + BOOL m_TimebarShowTime; ///< TRUE if timebars are to display their time value + BOOL m_InterpolationIsSmooth; ///< TRUE if default interpolation is smooth + QFont m_Font; ///< Font for text + QFont m_BoldFont; ///< Bold font for drawing the group boxes + void EnableOptions(); + void LoadSettings(); + void SaveSettings(); + + // Generated message map functions + virtual void OnInitDialog(); + void OnButtonRestoreDefaults(); + void OnSelChangeInterpolationDefault(); + void OnSelChangeSnapRange(); + void OnCheckTimelineAbsoluteSnapping(); + void OnChangeEditNudgeAmount(); + void OnSelChangeStartupView(); + void OnChangePreviewConfiguration(); + void OnBgColorButtonClicked(); + +protected: // helper functions + void InitEditStartViewCombo(); + +protected: + std::list<TBuildNameControlPair> + m_BuildProperties; ///< List of build properties, either ComboBox or Static + + void LoadPreviewSelections(); + void LoadBuildProperties(); + void SavePreviewSettings(); + void RemovePreviewPropertyControls(); + + QScopedPointer<Ui::StudioAppPrefsPage> m_ui; + +private: + void updateColorButton(); +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STUDIOAPPPREFSPAGE_H__FA329789_EEDD_4439_B6F6_AAD0FED5285F__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui new file mode 100644 index 00000000..5e1b88c5 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioAppPrefsPage.ui @@ -0,0 +1,183 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StudioAppPrefsPage</class> + <widget class="QWidget" name="StudioAppPrefsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>347</width> + <height>387</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>General</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Nudge Increment</string> + </property> + <property name="buddy"> + <cstring>m_editNudgeAmount</cstring> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Default Interpolation</string> + </property> + <property name="buddy"> + <cstring>m_DefaultInterpolation</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="m_DefaultInterpolation"/> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="m_checkTimelineAbsoluteSnapping"> + <property name="text"> + <string>Timeline Snapping Grid</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QComboBox" name="m_SnapRangeCombo"/> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="m_editNudgeAmount"/> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="m_groupBoxEditingView"> + <property name="title"> + <string>Editing View</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Background Color</string> + </property> + <property name="buddy"> + <cstring>m_EditViewBGColor</cstring> + </property> + </widget> + </item> + <item row="0" column="2" colspan="2"> + <widget class="QPushButton" name="m_EditViewBGColor"> + <property name="text"> + <string/> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Preferred Startup View</string> + </property> + <property name="buddy"> + <cstring>m_EditViewStartupView</cstring> + </property> + </widget> + </item> + <item row="1" column="2" colspan="2"> + <widget class="QComboBox" name="m_EditViewStartupView"/> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="m_buttonRestoreDefaults"> + <property name="maximumSize"> + <size> + <width>293</width> + <height>16777215</height> + </size> + </property> + <property name="text"> + <string>Restore Defaults</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBoxPreview"> + <property name="title"> + <string>Preview</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="1" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Configuration</string> + </property> + <property name="buddy"> + <cstring>m_PreviewSelector</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="m_PreviewSelector"/> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp new file mode 100644 index 00000000..747ba442 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.cpp @@ -0,0 +1,260 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" + +//============================================================================== +// Includes +//============================================================================== +#include "StudioPaletteBar.h" +#include "Preferences.h" +#include "StudioConst.h" +#include "PaletteState.h" +#include "StudioApp.h" + +//============================================================================== +// Message Maps +//============================================================================== +BEGIN_MESSAGE_MAP(CStudioPaletteBar, CViewBar) +//{{AFX_MSG_MAP(CStudioPaletteBar) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +// Constructors/Destructors +//============================================================================== + +CStudioPaletteBar::CStudioPaletteBar() +{ +} + +CStudioPaletteBar::~CStudioPaletteBar() +{ +} + +void CStudioPaletteBar::SetHorz(CSize inSize) +{ + m_szHorz.cx = max(m_szMinHorz.cx, inSize.cx); + m_szHorz.cy = max(m_szMinHorz.cy, inSize.cy); +} + +void CStudioPaletteBar::SetVert(CSize inSize) +{ + m_szVert.cx = max(m_szMinVert.cx, inSize.cx); + m_szVert.cy = max(m_szMinVert.cy, inSize.cy); +} + +void CStudioPaletteBar::SetFloat(CSize inSize) +{ + m_szFloat.cx = max(m_szMinFloat.cx, inSize.cx); + m_szFloat.cy = max(m_szMinFloat.cy, inSize.cy); +} + +//============================================================================== +/** + * Create: A wrapper around the CViewBar::Create() method. + * + * Simplifies the create parameters for the palette bar. + * + * @return BOOL The result from the Create() call (FALSE if unsuccessful) + */ +BOOL CStudioPaletteBar::Create(CString inTitle, CCreateContext *inCreateContext, long inControlId, + CWnd *theParent /* = nullptr */) +{ + BOOL theReturnValue; + + // Add the title of the bar to the registry location. + m_PaletteName = inTitle; + + // Create the palette bar. + theReturnValue = + CViewBar::Create(theParent, inCreateContext, inTitle, WS_CHILD | CBRS_TOP, inControlId); + ASSERT(theReturnValue == TRUE); + + SetBarStyle(GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC); + EnableDocking(CBRS_ALIGN_ANY); + + return theReturnValue; +} + +//============================================================================== +/** + * Call this function when the palette's view needs to be updated for the first + * time on application launch. + */ +void CStudioPaletteBar::InitialUpdate() +{ + // Send the update message to the attached CView + SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp)); +} + +//============================================================================== +/** + * Shows or hides the palette and saves the visibility. + * + * This function should be called instead of ShowWindow(), so that the visibility + * will be saved in the registry. + */ +void CStudioPaletteBar::ShowPalette(bool inState /* = true */) +{ + ShowWindow(inState ? SW_SHOW : SW_HIDE); + m_pDockSite->ShowControlBar(this, inState, FALSE); +} + +//============================================================================== +/** + * Query the view associated with this palette + */ +CView *CStudioPaletteBar::GetView() +{ + // Looks like the first grandchild is the view + return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD); +} + +//============================================================================== +// Message Maps +//============================================================================== +BEGIN_MESSAGE_MAP(CStudioDialog, CMiniFrameWnd) +//{{AFX_MSG_MAP(CStudioDialog) +//}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//============================================================================== +// Constructors/Destructors +//============================================================================== + +CStudioDialog::CStudioDialog() +{ +} + +CStudioDialog::~CStudioDialog() +{ +} + +//============================================================================== +/** + * Create: A wrapper around the CMiniFrameWnd::Create() method. + * + * Simplifies the create parameters for the palette bar. + * + * @return BOOL The result from the Create() call (FALSE if unsuccessful) + */ +/* +BOOL CStudioDialog::Create( CString inTitle, CCreateContext* inCreateContext, long inControlId, +CWnd* theParent ) +{ + BOOL theReturnValue; + + // Add the title of the bar to the registry location. + m_DialogName = inTitle; + + // Create the palette bar. + theReturnValue = CMiniFrameWnd::Create( theParent, inCreateContext, _T( inTitle ), WS_CHILD +| CBRS_TOP, inControlId ); + ASSERT( theReturnValue == TRUE ); + + SetBarStyle( GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC ); + EnableDocking(CBRS_ALIGN_ANY); + + return theReturnValue; +}*/ + +//============================================================================== +/** +* Create: A wrapper around the CMiniFrameWnd::Create() method. +* +* Simplifies the create parameters for the palette bar. +* +* @return BOOL The result from the Create() call (FALSE if unsuccessful) +*/ +//============================================================================== +BOOL CStudioDialog::Create(CString inTitle, CCreateContext *inCreateContext, + CWnd *theParent /* = nullptr */) +{ + CString theWndClass = AfxRegisterWndClass(CS_DBLCLKS, ::LoadCursor(nullptr, IDC_ARROW)); + BOOL theReturnValue; + + // Add the title of the bar to the registry location. + m_DialogName = inTitle; + + // Create the palette bar. + theReturnValue = CFrameWnd::Create( + theWndClass, inTitle, WS_SYSMENU | MFS_SYNCACTIVE | WS_POPUP | WS_CAPTION | MFS_THICKFRAME, + CRect(300, 300, 550, 800), theParent, nullptr, 0, inCreateContext); + + // Get the view to initialize. + this->InitialUpdateFrame(inCreateContext->m_pCurrentDoc, FALSE); + + // Get a handle to the system menu on the palette window + CMenu *theSystemMenu = GetSystemMenu(FALSE); + + // Remove the unwanted system menu items + theSystemMenu->DeleteMenu(SC_MINIMIZE, MF_BYCOMMAND); + theSystemMenu->DeleteMenu(SC_MAXIMIZE, MF_BYCOMMAND); + theSystemMenu->DeleteMenu(SC_RESTORE, MF_BYCOMMAND); + + return theReturnValue; +} + +//============================================================================== +/** + * Call this function when the palette's view needs to be updated for the first + * time on application launch. + */ +void CStudioDialog::InitialUpdate() +{ + // Send the update message to the attached CView + SendMessageToDescendants(WM_STUDIO_INITIALIZE_PALETTES, reinterpret_cast<WPARAM>(&g_StudioApp)); +} + +//============================================================================== +/** + * Shows or hides the dialog and saves the visibility. + * + * This function should be called instead of ShowWindow(), so that the visibility + * will be saved in the registry. + */ +void CStudioDialog::ShowDialog(bool inState /* = true */) +{ + ShowWindow(inState ? SW_SHOW : SW_HIDE); + // m_pDockSite->ShowControlBar( this, inState, FALSE ); +} + +//============================================================================== +/** + * Query the view associated with this palette + */ +CView *CStudioDialog::GetView() +{ + // Looks like the first grandchild is the view + return (CView *)GetWindow(GW_CHILD)->GetWindow(GW_CHILD); +} diff --git a/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h new file mode 100644 index 00000000..eed3fd05 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioPaletteBar.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_STUDIO_PALETTE_BAR_H +#define INCLUDED_STUDIO_PALETTE_BAR_H 1 + +#pragma once + +#include "ViewBar.h" + +class CStudioApp; +class CPaletteState; +class CStudioApp; + +class CStudioPaletteBar : public CViewBar +{ +public: + CStudioPaletteBar(); + virtual ~CStudioPaletteBar(); + + virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, long inControlId, + CWnd *theParent = nullptr); + + void ShowPalette(bool inState = true); + void InitialUpdate(); + CView *GetView(); + CSize GetHorz() { return m_szHorz; } + void SetHorz(CSize inSize); + CSize GetVert() { return m_szVert; } + void SetVert(CSize inSize); + CSize GetFloat() { return m_szFloat; } + void SetFloat(CSize inSize); + +protected: + Q3DStudio::CString m_PaletteName; + + //{{AFX_MSG(CStudioPaletteBar) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +class CStudioDialog : public CMiniFrameWnd +{ +public: + CStudioDialog(); + virtual ~CStudioDialog(); + + virtual BOOL Create(CString inTitle, CCreateContext *inCreateContext, CWnd *theParent = nullptr); + + void ShowDialog(bool inState = true); + void InitialUpdate(); + CView *GetView(); + +protected: + Q3DStudio::CString m_DialogName; + + //{{AFX_MSG(CStudioDialog) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#endif // INCLUDED_STUDIO_PALETTE_BAR_H diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp new file mode 100644 index 00000000..eb645d5e --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" + +#include "ui_StudioPreferencesPropSheet.h" + +//============================================================================== +// Includes +//============================================================================== +#include "StudioPreferences.h" +#include "StudioPreferencesPropSheet.h" +#include "StudioProjectSettingsPage.h" +#include "StringLoader.h" + +#include <QPushButton> + +CStudioPreferencesPropPage::CStudioPreferencesPropPage(QWidget *parent) + : QWidget(parent) +{ +} + +void CStudioPreferencesPropPage::SetModified(bool modified) +{ + setProperty("modified", modified); + + auto s = sheet(); + if (s) { + auto buttons = s->findChild<QDialogButtonBox *>(); + bool anyModified = false; + for (auto page : s->findChildren<CStudioPreferencesPropPage *>()) + anyModified |= page->property("modified").toBool(); + buttons->button(QDialogButtonBox::Apply)->setEnabled(anyModified); + } +} + +CStudioPreferencesPropSheet* CStudioPreferencesPropPage::sheet() +{ + QWidget *parent = parentWidget(); + while (parent != nullptr) { + if (auto sheet = qobject_cast<CStudioPreferencesPropSheet *>(parent)) + return sheet; + parent = parent->parentWidget(); + } + return nullptr; +} + + +void CStudioPreferencesPropPage::EndDialog(int returnCode) +{ + auto s = sheet(); + if (s) + s->done(returnCode); +} + +///////////////////////////////////////////////////////////////////////////// +// CStudioPreferencesPropSheet + +CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd, + int iSelectPage) + : QDialog(pParentWnd) + , m_ui(new Ui::StudioPreferencesPropSheet) +{ + setWindowTitle(::LoadResourceString(nIDCaption).toQString()); + OnInitDialog(); + m_ui->m_TabCtrl->setCurrentIndex(iSelectPage); +} + +CStudioPreferencesPropSheet::CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd, + int iSelectPage) + : QDialog(pParentWnd) + , m_ui(new Ui::StudioPreferencesPropSheet) +{ + setWindowTitle(pszCaption); + OnInitDialog(); + m_ui->m_TabCtrl->setCurrentIndex(iSelectPage); +} + +CStudioPreferencesPropSheet::~CStudioPreferencesPropSheet() +{ +} + +///////////////////////////////////////////////////////////////////////////// +// CStudioPreferencesPropSheet message handlers + +//============================================================================== +/** + * OnInitDialog: Handle the WM_INITDIALOG message to initialize the property sheet. + * + * @param None + */ +//============================================================================== +void CStudioPreferencesPropSheet::OnInitDialog() +{ + m_ui->setupUi(this); + m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); + + m_Font = QFont(CStudioPreferences::GetFontFaceName(), 8); + setFont(m_Font); + + connect(m_ui->buttonBox->button(QDialogButtonBox::Apply), &QPushButton::clicked, + this, &CStudioPreferencesPropSheet::apply); +} + +bool CStudioPreferencesPropSheet::apply() +{ + for (auto page : findChildren<CStudioPreferencesPropPage *>()) { + if (!page->OnApply()) + return false; + } + return true; +} + +void CStudioPreferencesPropSheet::accept() +{ + if (apply()) + QDialog::accept(); +} + +void CStudioPreferencesPropSheet::reject() +{ + for (auto page : findChildren<CStudioPreferencesPropPage *>()) + page->OnCancel(); + QDialog::reject(); +} diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h new file mode 100644 index 00000000..7057ba0f --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.h @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_) +#define AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_ + +#pragma once + +//============================================================================== +// Includes +//============================================================================== + +#include <QDialog> + +class CStudioProjectSettingsPage; +class CStudioPreferencesPropSheet; +class CStudioApp; + +namespace Ui +{ + class StudioPreferencesPropSheet; +} + +class CStudioPreferencesPropPage : public QWidget +{ + Q_OBJECT +public: + explicit CStudioPreferencesPropPage(QWidget *parent = nullptr); + + virtual bool OnApply() { OnOK(); SetModified(false); return true; } + virtual void OnOK() {} + virtual void OnCancel() {} + +protected: + CStudioPreferencesPropSheet* sheet(); + + void SetModified(bool modified); + void EndDialog(int returnCode); +}; + +///////////////////////////////////////////////////////////////////////////// +// CStudioPreferencesPropSheet + +class CStudioPreferencesPropSheet : public QDialog +{ + Q_OBJECT + // Construction +public: + explicit CStudioPreferencesPropSheet(int nIDCaption, QWidget *pParentWnd = nullptr, + int iSelectPage = 0); + explicit CStudioPreferencesPropSheet(const QString &pszCaption, QWidget *pParentWnd = nullptr, + int iSelectPage = 0); + +protected: + QFont m_Font; // Font for text + + // Implementation +public: + virtual ~CStudioPreferencesPropSheet(); + + // Generated message map functions +protected: + //{{AFX_MSG(CStudioPreferencesPropSheet) + virtual void OnInitDialog(); + + bool apply(); + void accept() override; + void reject() override; + +private: + QScopedPointer<Ui::StudioPreferencesPropSheet> m_ui; +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STUDIOPREFERENCESPROPSHEET_H__FADC69CE_5F0E_4F7E_A906_ED6052BBECF6__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui new file mode 100644 index 00000000..813d6016 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioPreferencesPropSheet.ui @@ -0,0 +1,102 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StudioPreferencesPropSheet</class> + <widget class="QDialog" name="StudioPreferencesPropSheet"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>484</width> + <height>466</height> + </rect> + </property> + <property name="windowTitle"> + <string>Studio Preferences</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTabWidget" name="m_TabCtrl"> + <widget class="CStudioAppPrefsPage" name="m_AppPrefsPage"> + <attribute name="icon"> + <iconset resource="../../MainFrm.qrc"> + <normaloff>:/res/prefstab-00.png</normaloff>:/res/prefstab-00.png</iconset> + </attribute> + <attribute name="title"> + <string>Studio</string> + </attribute> + </widget> + <widget class="CStudioProjectSettingsPage" name="m_ProjectSettingsPage"> + <attribute name="icon"> + <iconset resource="../../MainFrm.qrc"> + <normaloff>:/res/prefstab-01.png</normaloff>:/res/prefstab-01.png</iconset> + </attribute> + <attribute name="title"> + <string>Presentation Settings</string> + </attribute> + </widget> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>CStudioProjectSettingsPage</class> + <extends>QWidget</extends> + <header>StudioProjectSettingsPage.h</header> + <container>1</container> + </customwidget> + <customwidget> + <class>CStudioAppPrefsPage</class> + <extends>QWidget</extends> + <header>StudioAppPrefsPage.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources> + <include location="../../MainFrm.qrc"/> + </resources> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>StudioPreferencesPropSheet</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>StudioPreferencesPropSheet</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp new file mode 100644 index 00000000..c2a7e26c --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.cpp @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#include "stdafx.h" +#include "Strings.h" +#include "StringLoader.h" + +#include "ui_StudioProjectSettingsPage.h" + +//============================================================================== +// Includes +//============================================================================== +#include "StudioProjectSettingsPage.h" +#include "StudioProjectSettings.h" +#include "StudioApp.h" +#include "Doc.h" +#include "Views.h" +#include "MainFrm.h" +#include "CommonConstants.h" + +#include "StudioPreferences.h" +#include "Core.h" + +///////////////////////////////////////////////////////////////////////////// +// CStudioProjectSettingsPage property page + +//============================================================================== +/** + * Constructor: Initializes the object. + */ +//============================================================================== +CStudioProjectSettingsPage::CStudioProjectSettingsPage(QWidget *parent) + : CStudioPreferencesPropPage(parent) + , m_AspectRatio(0.0f) + , m_ui(new Ui::StudioProjectSettingsPage) +{ + m_Font = QFont(CStudioPreferences::GetFontFaceName()); + m_Font.setPixelSize(CStudioPreferences::fontSize()); + + // Create a bold font for the group box text + m_BoldFont = m_Font; + m_BoldFont.setBold(true); + + OnInitDialog(); +} + +//============================================================================== +/** + * Destructor: Releases the object. + */ +//============================================================================== +CStudioProjectSettingsPage::~CStudioProjectSettingsPage() +{ +} + +//============================================================================== +// Message Map is defined by subclasses, since there is any specific handlers must be +// defined within the BEGIN_MESSAGE_MAP macros. +//============================================================================== + +///////////////////////////////////////////////////////////////////////////// +// CStudioProjectSettingsPage message handlers + +//============================================================================== +/** + * OnInitDialog: Handle the WM_INITDIALOG message. + * + * Initialize the dialog by setting the various control values. + * + * @param None + * + * @return Returns TRUE always. + */ +//============================================================================== +void CStudioProjectSettingsPage::OnInitDialog() +{ + m_ui->setupUi(this); + + m_ui->m_ClientSizeWidth->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONWIDTH).toQString()); + m_ui->m_ClientSizeHeight->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONHEIGHT).toQString()); + m_ui->m_checkConstrainProportions->setToolTip(::LoadResourceString(IDS_PREFS_PRESENTATIONASPECTRATIO).toQString()); + m_ui->m_Author->setToolTip(::LoadResourceString(IDS_PREFS_AUTHORNAME).toQString()); + m_ui->m_Company->setToolTip(::LoadResourceString(IDS_PREFS_COMPANYNAME).toQString()); + + // Set fonts for child windows. + for (auto w : findChildren<QWidget *>()) + w->setFont(m_Font); + + // Make the group text bold + for (auto w : findChildren<QGroupBox *>()) + w->setFont(m_BoldFont); + + // Set the ranges of the client width and height + m_ui->m_ClientSizeWidth->setRange(1, 16384); + m_ui->m_ClientSizeHeight->setRange(1, 16384); + + // Load the settings for the controls + this->LoadSettings(); + + auto valueChanged = static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged); + connect(m_ui->m_ClientSizeWidth, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresWidth); + connect(m_ui->m_ClientSizeHeight, valueChanged, this, &CStudioProjectSettingsPage::OnChangeEditPresHeight); + connect(m_ui->m_checkConstrainProportions, &QCheckBox::clicked, this, &CStudioProjectSettingsPage::OnCheckMaintainRatio); + connect(m_ui->m_Author, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeAuthor); + connect(m_ui->m_Company, &QLineEdit::textEdited, this, &CStudioProjectSettingsPage::OnChangeCompany); +} + +//============================================================================== +/** + * LoadSettings: Load the settings from the project settings and set the control values. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::LoadSettings() +{ + // Get the Client size + CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings(); + CPt theClientSize = theProjectSettings->GetPresentationSize(); + + // Set client width & height + m_ui->m_ClientSizeWidth->setValue(theClientSize.x); + m_ui->m_ClientSizeHeight->setValue(theClientSize.y); + + // Save the aspect ratio + m_AspectRatio = (double)theClientSize.x / (double)theClientSize.y; + + // Maintain Aspect Ratio checkbox + m_ui->m_checkConstrainProportions->setChecked(theProjectSettings->GetMaintainAspect()); + + m_ui->m_checkPortraitFormat->setChecked(theProjectSettings->GetRotatePresentation()); + + // Author + m_ui->m_Author->setText(theProjectSettings->GetAuthor()); + + // Company + m_ui->m_Company->setText(theProjectSettings->GetCompany()); +} + +//============================================================================== +/** + * SaveSettings: Save the settings from the controls to the project settings. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::SaveSettings() +{ + CPt theClientSize; + CStudioProjectSettings *theProjectSettings = g_StudioApp.GetCore()->GetStudioProjectSettings(); + + // Presentation width & height + theClientSize.x = m_ui->m_ClientSizeWidth->value(); + theClientSize.y = m_ui->m_ClientSizeHeight->value(); + theProjectSettings->SetPresentationSize(theClientSize); + + // Author + QString theAuthor = m_ui->m_Author->text(); + theProjectSettings->SetAuthor(theAuthor); + + // Company + QString theCompany = m_ui->m_Company->text(); + theProjectSettings->SetCompany(theCompany); + + g_StudioApp.GetViews()->RecheckMainframeSizingMode(); + + // Maintain Aspect Ratio checkbox + theProjectSettings->SetMaintainAspect(m_ui->m_checkConstrainProportions->isChecked()); + + theProjectSettings->SetRotatePresentation(m_ui->m_checkPortraitFormat->isChecked()); +} + +//============================================================================== +/** + * Generic function when settings are modified. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnSettingsModified() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnApply: Handler for the Apply button + * + * @param None + */ +//============================================================================== +bool CStudioProjectSettingsPage::OnApply() +{ + // Apply was clicked - save settings and disabled the Apply button + this->SaveSettings(); + + this->SetModified(FALSE); + + return CStudioPreferencesPropPage::OnApply(); +} + +//============================================================================== +/** + * OnOK: Handler for the OK button + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnOK() +{ + CStudioPreferencesPropPage::OnOK(); +} + +//============================================================================== +/** + * OnChangeEditPresWidth: EN_CHANGE handler for the IDC_EDIT_PRESWIDTH field + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeEditPresWidth() +{ + this->SetModified(TRUE); + + // Should the aspect ratio be maintained? + if (m_ui->m_checkConstrainProportions->isChecked()) { + long thePresWidth, thePresHeight; + + thePresWidth = m_ui->m_ClientSizeWidth->value(); + + // Change the height + thePresHeight = ((double)thePresWidth / m_AspectRatio); + + QSignalBlocker sb(m_ui->m_ClientSizeHeight); + m_ui->m_ClientSizeHeight->setValue(thePresHeight); + } +} + +//============================================================================== +/** + * OnChangeEditPresHeight: EN_CHANGE handler for the IDC_EDIT_PRESHEIGHT field + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeEditPresHeight() +{ + this->SetModified(TRUE); + + // Should the aspect ratio be maintained? + if (m_ui->m_checkConstrainProportions->isChecked()) { + long thePresWidth, thePresHeight; + + thePresHeight = m_ui->m_ClientSizeHeight->value(); + + // Change the width + thePresWidth = ((double)thePresHeight * m_AspectRatio); + + QSignalBlocker sb(m_ui->m_ClientSizeWidth); + m_ui->m_ClientSizeWidth->setValue(thePresWidth); + } +} + +//============================================================================== +/** + * OnCheckMaintainRatio: The aspect ratio checkbox has changed. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnCheckMaintainRatio() +{ + this->SetModified(TRUE); + + long thePresWidth, thePresHeight; + + // Get the width and height + thePresWidth = m_ui->m_ClientSizeWidth->value(); + thePresHeight = m_ui->m_ClientSizeHeight->value(); + + // Save the Aspect Ratio + m_AspectRatio = (double)thePresWidth / (double)thePresHeight; +} + +//============================================================================== +/** + * OnChangeAuthor: EN_CHANGE handler for the IDC_AUTHOR field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeAuthor() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeCompany: EN_CHANGE handler for the IDC_COMPANY field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeCompany() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeSet1: EN_CHANGE handler for the IDC_SET1 field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeSet1() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeSet2: EN_CHANGE handler for the IDC_SET2 field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeSet2() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeSet3: EN_CHANGE handler for the IDC_SET3 field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeSet3() +{ + this->SetModified(TRUE); +} + +//============================================================================== +/** + * OnChangeSet5: EN_CHANGE handler for the IDC_SET5 field. + * + * @param None + */ +//============================================================================== +void CStudioProjectSettingsPage::OnChangeSet5() +{ + this->SetModified(TRUE); +} diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h new file mode 100644 index 00000000..64465e98 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_) +#define AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//============================================================================== +// Includes +//============================================================================== + +//#include "ParameterColor.h" + +#include "StudioPreferencesPropSheet.h" + +#ifdef _USENEWCOLORPICKER_ +#include "StudioColorPicker.h" +#endif + +//============================================================================== +// Forwards +//============================================================================== +class CStudioApp; + +namespace Ui { + class StudioProjectSettingsPage; +} + +//============================================================================== +// Base class for the settings for different modes +//============================================================================== +class CStudioProjectSettingsPage : public CStudioPreferencesPropPage +{ + Q_OBJECT + // Construction +public: + explicit CStudioProjectSettingsPage(QWidget *parent = nullptr); + ~CStudioProjectSettingsPage(); + + // Overrides + // ClassWizard generate virtual function overrides +public: + bool OnApply() override; + void OnOK() override; + + // Implementation +protected: + double m_AspectRatio; ///< Stores the presentation width divided by the presentation height + QFont m_Font; ///< Font for text + QFont m_BoldFont; ///< Bold font for drawing the group boxes + + void LoadSettings(); + void SaveSettings(); + +protected: + // Generated message map functions + virtual void OnInitDialog(); + void OnChangeEditPresWidth(); + void OnChangeEditPresHeight(); + void OnCheckMaintainRatio(); + void OnChangeAuthor(); + void OnChangeCompany(); + void OnSettingsModified(); + void OnSelChangePreviewApp(); + void OnCustomPreviewMore(); + void OnChangeSet1(); + void OnChangeSet2(); + void OnChangeSet3(); + void OnChangeSet5(); + + QScopedPointer<Ui::StudioProjectSettingsPage> m_ui; +}; + +#endif // !defined(AFX_STUDIOPROJECTSETTINGSPAGE_H__E3317E44_810D_4478_A7DD_CF8570B7C17C__INCLUDED_) diff --git a/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui new file mode 100644 index 00000000..07a4bf65 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/StudioProjectSettingsPage.ui @@ -0,0 +1,125 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>StudioProjectSettingsPage</class> + <widget class="QWidget" name="StudioProjectSettingsPage"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>259</width> + <height>269</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Presentation</string> + </property> + <layout class="QFormLayout" name="formLayout_2"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Width x Height</string> + </property> + <property name="buddy"> + <cstring>m_ClientSizeWidth</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QSpinBox" name="m_ClientSizeWidth"> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="m_ClientSizeHeight"> + <property name="buttonSymbols"> + <enum>QAbstractSpinBox::NoButtons</enum> + </property> + </widget> + </item> + </layout> + </item> + <item row="2" column="0" colspan="2"> + <widget class="QCheckBox" name="m_checkConstrainProportions"> + <property name="text"> + <string>Constrain Proportions</string> + </property> + </widget> + </item> + <item row="4" column="0" colspan="2"> + <widget class="QCheckBox" name="m_checkPortraitFormat"> + <property name="text"> + <string>Portrait Format</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Project Info</string> + </property> + <layout class="QFormLayout" name="formLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Author</string> + </property> + <property name="buddy"> + <cstring>m_Author</cstring> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="m_Author"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Company</string> + </property> + <property name="buddy"> + <cstring>m_Company</cstring> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="m_Company"/> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + </layout> + </widget> + <tabstops> + <tabstop>m_ClientSizeWidth</tabstop> + <tabstop>m_ClientSizeHeight</tabstop> + <tabstop>m_checkConstrainProportions</tabstop> + <tabstop>m_checkPortraitFormat</tabstop> + <tabstop>m_Author</tabstop> + <tabstop>m_Company</tabstop> + </tabstops> + <resources/> + <connections/> +</ui> diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp new file mode 100644 index 00000000..619d7651 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.cpp @@ -0,0 +1,524 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================= +// Prefix +//============================================================================= + +#include "ui_timeeditdlg.h" + +#include "stdafx.h" +#include "StudioPreferences.h" +#include "Strings.h" +#include "StringLoader.h" + +//============================================================================== +// Includes +//============================================================================== + +#include "TimeEditDlg.h" +#include "IDoc.h" +#include "Bindings/ITimelineKeyframesManager.h" + +#include <QFont> +#include <QPalette> + +//============================================================================= +/** + * Constructor + */ +CTimeEditDlg::CTimeEditDlg(QWidget *pParent) + : QDialog(pParent) + , m_MaxTime(0) + , m_MaxTimeDisplay(0) + , m_MinTimeDisplay(0) + , m_InitialTime1(0) + , m_InitialTime2(0) + , m_MinOffset(0) + , m_SecOffset(0) + , m_MSecOffset(0) + , m_MinMinorOffset(0) + , m_SecMinorOffset(0) + , m_MSecMinorOffset(0) + , m_CursorPosition(0) + , m_TimeFormat(0) + , m_PreviousFormat(0) + , m_TimeInMins(0.0f) + , m_NumberOfDigitsDrop(0) + , m_ColonPosition1(0) + , m_ColonPosition2(0) + , m_ObjectAssociation(0) + , m_OffsetFromInitialTime(0) + , m_Time1(0) + , m_Time2(0) + , m_Doc(nullptr) + , m_KeyframesManager(nullptr) + , m_Callback(nullptr) + , m_ui(new Ui::TimeEditDlg) +{ + m_ui->setupUi(this); + setAutoFillBackground(true); + + connect(m_ui->startTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit1); + connect(m_ui->endTimeEdit, &QDateTimeEdit::timeChanged, this, &CTimeEditDlg::OnEnChangeTimeEdit2); +} + +//============================================================================= +/** + * Destructor + */ +CTimeEditDlg::~CTimeEditDlg() +{ + delete m_ui; +} + +void CTimeEditDlg::SetKeyframesManager(ITimelineKeyframesManager *inKeyframesManager) +{ + m_KeyframesManager = inKeyframesManager; +} + +//============================================================================= +/** + * InitData: Initializes the Time Edit Dialog Box. + * @param inTime1 is the intial start time, which will be shown when the time edit + * dialog box pops up + * @param inTime2 is the intial end time, which will be shown when the time edit + * dialog box pops up + * @param inDoc this can be nullptr where its not applicable + * @param inObjectAssociation is the identifier for that identifies the object + * associated with the time edit dialog + *(e.g. + * playhead, keyframe, timebar) + */ +void CTimeEditDlg::ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation, + ITimeChangeCallback *inCallback /*= nullptr*/) +{ + m_InitialTime1 = inTime1; + m_InitialTime2 = inTime2; + m_ObjectAssociation = inObjectAssociation; + m_Doc = inDoc; + m_Callback = inCallback; + + m_OffsetFromInitialTime = 0; + m_NumberOfDigitsDrop = 0; + m_MinTimeDisplay = 0; + // if it is a Timebar, this will be adjusted, else this should be initialized to some value at + // least, + // for OverflowHandling to work correctly + m_MaxTimeDisplay = LONG_MAX; + + // 9999:59:999 converted to milliseconds + m_MaxTime = + TimeConversion(9999, CONVERT_MIN_TO_MSEC) + TimeConversion(59, CONVERT_SEC_TO_MSEC) + 999; + + m_TimeDisplay2 = FormatTime(m_InitialTime2); + // In cases Keyframes, where its only one set of time, do m_InitialTime1 later so that + // m_Min, etc. values are initializd to the valid values. + m_TimeDisplay1 = FormatTime(m_InitialTime1); + + // Present the dialog + exec(); +} + +//============================================================================== +/** + * FormatTime: Called to break up a given time in milliseconds into min:sec:msec + * store it in a string. The string is formatted in 99:59:999 form. + * @param inTime stores the time in milliseconds, which will be converted + * and stored in ioTimeString in 99:59:999 format. + * @return ioTimeString stores the result of the FormatTime method. + */ +QString CTimeEditDlg::FormatTime(long inTime) +{ + long theTime = inTime; + long hour = 0; + long min = 0; + long sec = 0; + long msec = 0; + // Translates the m_InitialTime1 (in milliseconds) into Minutes, Seconds and Milliseconds + if (inTime != 0) { + min = TimeConversion(theTime, CONVERT_MSEC_TO_MIN); + hour = min / 60; + theTime = theTime - TimeConversion(min, CONVERT_MIN_TO_MSEC); + min -= hour * 60; + sec = TimeConversion(theTime, CONVERT_MSEC_TO_SEC); + theTime = theTime - TimeConversion(sec, CONVERT_SEC_TO_MSEC); + msec = theTime; + } + return QString::asprintf("%02d:%02d:%02d:%03d", hour, min, sec, msec); +} + +//============================================================================== +/** + * OnInitDialog: Handle the WM_INITDIALOG message. + * @param None + * @return Returns TRUE always. + */ +void CTimeEditDlg::showEvent(QShowEvent *ev) +{ + OnInitDialog(); + QDialog::showEvent(ev); +} + + +void CTimeEditDlg::OnInitDialog() +{ + // Hide the window items associated with end time. + if (m_ObjectAssociation != TIMEBAR) + HideUnnecessaryFields(); + m_ui->startTimeEdit->setTime(QTime::fromString(m_TimeDisplay1, "hh:mm:ss:zzz")); + Q3DStudio::CString theTitle; + // Display the window captions for the correct object type + switch (m_ObjectAssociation) { + case PLAYHEAD: + theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_GO_TO_TIME); + setWindowTitle(theTitle.toQString()); + break; + case ASSETKEYFRAME: + theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_KEYFRAME_TIME); + setWindowTitle(theTitle.toQString()); + break; + case TIMEBAR: + theTitle = ::LoadResourceString(IDS_TIME_EDIT_DLG_SET_TIMEBAR_TIME); + // m_TimeEditBoxNumber is a flag that switches the output between + // the first and second text box. + // When m_TimeEditBoxNumber = EDITBOX1, we are writing to the first text box + // (the one that appears on top). + // When it is EDITBOX2, the SetTimeEdit will write to the second text box. + setWindowTitle(theTitle.toQString()); + m_ui->endTimeEdit->setTime(QTime::fromString(m_TimeDisplay2, "hh:mm:ss:zzz")); + break; + } +} +//============================================================================== +/** + * accept: Upon clicking ok, the dialog will be exited + */ +void CTimeEditDlg::accept() +{ + // Only commit here, cos dup keyframes will be deleted. + if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager) + m_KeyframesManager->CommitChangedKeyframes(); + else if (m_ObjectAssociation == TIMEBAR) + m_Callback->Commit(); + + QDialog::accept(); +} + +//============================================================================== +/** + * reject: Upon clicking Cancel, revert to the initial time. + */ +void CTimeEditDlg::reject() +{ + // Only commit here, cos dup keyframes will be deleted. + if (m_ObjectAssociation == ASSETKEYFRAME && m_Doc && m_KeyframesManager) + m_KeyframesManager->RollbackChangedKeyframes(); + else if (m_ObjectAssociation == TIMEBAR) + m_Callback->Rollback(); + QDialog::reject(); +} + +//============================================================================== +/** + * CountDigits: Counts the number of digits in a given number + * @param inNumber is the number that is used to count the number of digits + * @return the number of digits + */ +long CTimeEditDlg::CountDigits(long inNumber) +{ + long theNumberOfDigits = 0; + for (long theNumber = inNumber; theNumber >= 1; theNumber = theNumber / 10) + theNumberOfDigits++; + return theNumberOfDigits; +} + + +//============================================================================== +/** + * TimeOverflowUnderflow: Checks if inMin, inSec or inMSec has exceeded the overflow/ + * underflow limit. It will correct the time if it + *overflow/ + * underflow. + * @param inMin stores the min segment of the time + * @param inSec stores the sec segment of the time + * @param inMSec stores the msec segment of the time + * @param inTimeLimit stores the time limit before the overflow/underflow occurs + * @param inOverflowOrUnderflow is set to true if we are checking for overflow else + * we are checking for underflow + * @returns true if overflow/underflow occurs, otherwise returns false. + */ +bool CTimeEditDlg::TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit, + bool inOverflowOrUnderflow) +{ + // The codes below translates inTimeLimit into theLimitMin:theLimitSec:theLimitMsec + bool theLimitExceeds = false; + long theLimitMin; + long theLimitSec; + long theLimitMsec; + TimeConversion(inTimeLimit, &theLimitMin, &theLimitSec, &theLimitMsec, + CONVERT_MSEC_TO_MIN_SEC_MSEC); + // Handle time overflow/underflow + if ((*inMin > theLimitMin && inOverflowOrUnderflow) + || (*inMin < theLimitMin && inOverflowOrUnderflow == false)) // Minutes exceeds limit + { + // Set all time segments to the limit + *inMin = theLimitMin; + *inSec = theLimitSec; + *inMSec = theLimitMsec; + theLimitExceeds = true; + } else if (*inMin == theLimitMin) { + if ((*inSec > theLimitSec && inOverflowOrUnderflow) + || (*inSec < theLimitSec && inOverflowOrUnderflow == false)) // Seconds exceeds limit + { + // Set the Sec and Msec segments to the limit + *inSec = theLimitSec; + *inMSec = theLimitMsec; + theLimitExceeds = true; + } else if (*inSec == theLimitSec) { + if ((*inMSec > theLimitMsec && inOverflowOrUnderflow) + || (*inMSec < theLimitMsec + && inOverflowOrUnderflow == false)) // Milliseconds exceeds limit + { + // Msec segments to the limit + *inMSec = theLimitMsec; + theLimitExceeds = true; + } + } + } + return theLimitExceeds; +} + +//============================================================================== +/** + * TimeConversion: Converts inTime to the format specified by inFlags. + * For example: + * inTime = 5 sec inFlags = CONVERT_SEC_TO_MSEC + * The method will convert 5 sec into 5000 msec and + *returns + * the result. + * @param inTime stores the time to be converted. + * inOperationCode determines the type of time conversion to be done on the + * inTime. + * @return theResult stores the result of the time conversion. + */ +long CTimeEditDlg::TimeConversion(long inTime, long inOperationCode) +{ + long theResult = 0; + switch (inOperationCode) { + case CONVERT_MIN_TO_MSEC: + theResult = inTime * 60 * 1000; + break; + case CONVERT_SEC_TO_MSEC: + theResult = inTime * 1000; + break; + case CONVERT_MSEC_TO_MIN: + theResult = inTime / (60 * 1000); + break; + case CONVERT_MSEC_TO_SEC: + theResult = inTime / 1000; + break; + } + return theResult; +} + +//============================================================================== +/** + * TimeConversion: Takes in the time in mins:secs:msec and convert it to + * the corresponding time in msec. + * @param inMin stores the minutes to be converted. + * inSec stores the seconds to be converted. + * inMsec stores the milliseconds to be converted. + * inOperationCode determines the type of time conversion to be done on the + * inMin, inSec and inMsec. + * @return theResult stores the result of the time conversion. + */ +long CTimeEditDlg::TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode) +{ + long theResult = 0; + switch (inOperationCode) { + case CONVERT_TIME_TO_MSEC: + theResult = TimeConversion(inMin, CONVERT_MIN_TO_MSEC) + + TimeConversion(inSec, CONVERT_SEC_TO_MSEC) + inMsec; + break; + } + return theResult; +} + +//============================================================================== +/** + * TimeConversion: Takes in the time in milliseconds and converts them + * to min : sec : msec. + * @param inTotalTime stores the total time in msec. + * ioMin stores the mins result of the time conversion + * ioSec stores the secs result of the time conversion + * ioMsec stores the msecs result of the time conversion + * inOperationCode determines the type of time conversion to be done on the + * inTotalTime. + * @return NONE + */ +void CTimeEditDlg::TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec, + long inOperationCode) +{ + switch (inOperationCode) { + case CONVERT_MSEC_TO_MIN_SEC_MSEC: + *ioMin = TimeConversion(inTotalTime, CONVERT_MSEC_TO_MIN); + *ioSec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC); + *ioSec = TimeConversion(*ioSec, CONVERT_MSEC_TO_SEC); + *ioMsec = inTotalTime - TimeConversion(*ioMin, CONVERT_MIN_TO_MSEC) + - TimeConversion(*ioSec, CONVERT_SEC_TO_MSEC); + break; + } +} +//============================================================================== +/** + * UpdateObjectTime: It updates the playhead, keyframe or timebar time according + * to the time displayed in the time edit dialogue. + * @param inTime is the time that will be updated. + * @param startTime if true, updates the start time on the object, otherwise the end time + * @return NONE + */ +void CTimeEditDlg::UpdateObjectTime(long inTime, bool startTime) +{ + long theDiff = 0; + switch (m_ObjectAssociation) { + case PLAYHEAD: // Update the playhead time + if (m_Doc) { + m_Doc->NotifyTimeChanged(inTime); + m_Doc->NotifyTimeChanged(inTime); + } + break; + case ASSETKEYFRAME: // Update the keyframe time + if (m_Doc) { + theDiff = inTime - m_OffsetFromInitialTime - m_InitialTime1; + m_OffsetFromInitialTime = m_OffsetFromInitialTime + theDiff; + if (theDiff != 0 && m_KeyframesManager) { + m_KeyframesManager->OffsetSelectedKeyframes(theDiff); + } + } + break; + case TIMEBAR: // Update the timebar start/end time + if (m_Callback) { + if (startTime) // Update Start Time + m_Callback->ChangeStartTime(inTime); + else // Update End Time + m_Callback->ChangeEndTime(inTime); + } + break; + } +} + +//============================================================================== +/** The codes methods below are provides platform independent wrappers for + * User Interface. + */ +//============================================================================== + +/** + * OnEnChangeTimeEdit: Event triggered when the text in the 1st time edit box has + * been changed. + * @param NONE + * @return NONE + */ +void CTimeEditDlg::OnEnChangeTimeEdit1() +{ + // Making sure that the start time is not greater than the end time, when + // the user modifies the start time of the timebar + if (m_ObjectAssociation == TIMEBAR) { + m_MaxTimeDisplay = m_InitialTime2; // the initial end time + } + m_MinTimeDisplay = 0; + + const auto time = m_ui->startTimeEdit->time(); + long min = time.minute() + time.hour() * 60; + long sec = time.second(); + long msec = time.msec(); + TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true); + TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false); + if (min != time.minute() || sec != time.second() || + msec != time.msec()) { + m_ui->startTimeEdit->setTime(QTime(0, min, sec, msec)); + } + m_ui->startTimeMin->setText(QString::number(min)); + m_ui->startTimeSec->setText(QString::number(sec)); + m_ui->startTimeMsec->setText(QString::number(msec)); + + long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC) + + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec; + // Go to the time specified in the time edit display + UpdateObjectTime(theGoToTime, true /*start time*/); +} + +//============================================================================== +/** + * OnEnChangeTimeEdit2: Event triggered when the text in the 2nd time edit box has + * been changed. + * @param NONE + * @return NONE + */ +void CTimeEditDlg::OnEnChangeTimeEdit2() +{ + // Let the end time of the time bar go as far as possible + if (m_ObjectAssociation == TIMEBAR) { + m_MaxTimeDisplay = m_MaxTime; + m_MinTimeDisplay = m_InitialTime1; // the initial start time + } + const auto time = m_ui->endTimeEdit->time(); + long min = time.minute() + time.hour() * 60; + long sec = time.second(); + long msec = time.msec(); + TimeOverflowUnderflow(&min, &sec, &sec, m_MaxTimeDisplay, true); + TimeOverflowUnderflow(&min, &sec, &msec, m_MinTimeDisplay, false); + if (min != time.minute() || sec != time.second() || + msec != time.msec()) { + m_ui->endTimeEdit->setTime(QTime(0, min, sec, msec)); + } + m_ui->endTimeMin->setText(QString::number(min)); + m_ui->endTimeSec->setText(QString::number(sec)); + m_ui->endTimeMsec->setText(QString::number(msec)); + + long theGoToTime = TimeConversion(min, CONVERT_MIN_TO_MSEC) + + TimeConversion(sec, CONVERT_SEC_TO_MSEC) + msec; + // Go to the time specified in the time edit display + UpdateObjectTime(theGoToTime, false /*end time*/); +} + + +//============================================================================== +/** + * HideUnnecessaryFields: Hides unused dialog items + * @param NONE + * @return NONE + */ +void CTimeEditDlg::HideUnnecessaryFields() +{ + m_ui->endTimeGroup->hide(); + m_ui->startTimeLabel->hide(); +} + diff --git a/src/Authoring/Studio/_Win/UI/TimeEditDlg.h b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h new file mode 100644 index 00000000..7103dd3e --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/TimeEditDlg.h @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== + +#ifndef INCLUDED_TIME_EDIT_DIALOG_H +#define INCLUDED_TIME_EDIT_DIALOG_H 1 + +//============================================================================== +// Includes +//============================================================================== +#include "Dialogs.h" +#include <QDialog> +#include <QDateTimeEdit> + +//============================================================================== +// Forwards +//============================================================================== +class CTimebarControl; +class IDoc; +class ITimelineKeyframesManager; + +//============================================================================== +// Defines +//============================================================================== + +enum ECursorPosition { MIN_POSITION, SEC_POSITION, MSEC_POSITION }; + +enum ETimeFormat { MSEC, SEC_MSEC, MIN_SEC_MSEC }; + +enum ETimeConversionOperation { + CONVERT_MIN_TO_MSEC, + CONVERT_SEC_TO_MSEC, + CONVERT_MSEC_TO_MIN, + CONVERT_MSEC_TO_SEC, + CONVERT_TIME_TO_MSEC, + CONVERT_MSEC_TO_MIN_SEC_MSEC +}; + +enum ETimeEditBoxNumber { EDITBOX1, EDITBOX2 }; + +enum EObjectAssociation { + PLAYHEAD, + ASSETKEYFRAME, + TIMEBAR, +}; + +class ITimeChangeCallback +{ +public: + virtual ~ITimeChangeCallback() {} + virtual void ChangeStartTime(long) = 0; + virtual void ChangeEndTime(long) = 0; + virtual void Commit() = 0; + virtual void Rollback() = 0; +}; + +#ifdef QT_NAMESPACE +using namespace QT_NAMESPACE; +#endif + +QT_BEGIN_NAMESPACE +namespace Ui { + class TimeEditDlg; +} +QT_END_NAMESPACE + +// This class workaround the problem of QDateTimeEdit overwriting the selected section +// See https://bugreports.qt.io/browse/QTBUG-34759 +class CDateTimeEdit : public QDateTimeEdit +{ + Q_OBJECT +public: + using QDateTimeEdit::QDateTimeEdit; + +protected: + void focusInEvent(QFocusEvent *event) { + QDateTimeEdit::focusInEvent(event); + setSelectedSection(QDateTimeEdit::SecondSection); + } +}; + +//============================================================================== +/** + * CTimeEditDlg: It is a dialog box that allows user to specify the time that + * he/she wishes to go to. This dialog box can be activated by + * pressing Control G or clicking on the time edit box in the + * timeline. + */ +//============================================================================== +class CTimeEditDlg : public QDialog +{ + Q_OBJECT + +public: + CTimeEditDlg(QWidget *pParent = nullptr); // standard constructor + virtual ~CTimeEditDlg(); + void SetKeyframesManager(ITimelineKeyframesManager *inKeyframeManager); + void ShowDialog(long inTime1, long inTime2, IDoc *inDoc, long inObjectAssociation, + ITimeChangeCallback *inCallback = nullptr); + +public Q_SLOTS: + void accept() override; + void reject() override; + +protected: + void showEvent(QShowEvent *) override; + + // Generated message map functions + void OnInitDialog(); + void OnEnChangeTimeEdit1(); + void OnEnChangeTimeEdit2(); + + QString FormatTime(long inTime); + long CountDigits(long inNumber); + long TimeConversion(long inTime, long inOperationCode); + long TimeConversion(long inMin, long inSec, long inMsec, long inOperationCode); + void TimeConversion(long inTotalTime, long *ioMin, long *ioSec, long *ioMsec, + long inOperationCode); + void UpdateObjectTime(long inTime, bool startTime); + bool TimeOverflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit); + bool TimeOverflowUnderflow(long *inMin, long *inSec, long *inMSec, long inTimeLimit, + bool inOverflowOrUnderflow); + void HideUnnecessaryFields(); + +protected: + QString m_MinString; + QString m_SecString; + QString m_MSecString; + QString m_TimeDisplay1; + QString m_TimeDisplay2; + long m_MaxTime; + long m_MaxTimeDisplay; + long m_MinTimeDisplay; + long m_InitialTime1; + long m_InitialTime2; + long m_MinOffset; + long m_SecOffset; + long m_MSecOffset; + long m_MinMinorOffset; + long m_SecMinorOffset; + long m_MSecMinorOffset; + long m_CursorPosition; + long m_TimeFormat; + long m_PreviousFormat; + double m_TimeInMins; + long m_NumberOfDigitsDrop; + long m_ColonPosition1; + long m_ColonPosition2; + long m_ObjectAssociation; + long m_OffsetFromInitialTime; + QString m_DTime; + QString m_DTimeDisplay; + long m_Time1; + long m_Time2; + IDoc *m_Doc; + ITimelineKeyframesManager *m_KeyframesManager; + + ITimeChangeCallback *m_Callback; + Ui::TimeEditDlg *m_ui; +}; +#endif // INCLUDED_TIME_EDIT_DIALOG_H diff --git a/src/Authoring/Studio/_Win/UI/timeeditdlg.ui b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui new file mode 100644 index 00000000..f46cb1a2 --- /dev/null +++ b/src/Authoring/Studio/_Win/UI/timeeditdlg.ui @@ -0,0 +1,364 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TimeEditDlg</class> + <widget class="QDialog" name="TimeEditDlg"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>371</width> + <height>274</height> + </rect> + </property> + <property name="windowTitle"> + <string>Go To Time</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <spacer name="verticalSpacer_2"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QWidget" name="startTimeGroup" native="true"> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="2" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="CDateTimeEdit" name="startTimeEdit"> + <property name="currentSection"> + <enum>QDateTimeEdit::SecondSection</enum> + </property> + <property name="displayFormat"> + <string>hh:mm:ss:zzz</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="1" column="1"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="startTimeMin"> + <property name="text"> + <string>00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_7"> + <property name="text"> + <string>sec</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="startTimeSec"> + <property name="text"> + <string>00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>min</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QLabel" name="startTimeMsec"> + <property name="text"> + <string>000</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="startTimeLabel"> + <property name="text"> + <string>Start Time</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QWidget" name="endTimeGroup" native="true"> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="endTimeLabel"> + <property name="text"> + <string>End Time</string> + </property> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="CDateTimeEdit" name="endTimeEdit"> + <property name="currentSection"> + <enum>QDateTimeEdit::SecondSection</enum> + </property> + <property name="displayFormat"> + <string>hh:mm:ss:zzz</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_6"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Fixed</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="1" column="1"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="endTimeMin"> + <property name="text"> + <string>00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>sec</string> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="endTimeSec"> + <property name="text"> + <string>00</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>min</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QLabel" name="endTimeMsec"> + <property name="text"> + <string>000</string> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>:</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="horizontalSpacer_7"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeType"> + <enum>QSizePolicy::Expanding</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer_4"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>CDateTimeEdit</class> + <extends>QTimeEdit</extends> + <header>TimeEditDlg.h</header> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>TimeEditDlg</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>TimeEditDlg</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui> diff --git a/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp new file mode 100644 index 00000000..9cd7328d --- /dev/null +++ b/src/Authoring/Studio/_Win/Utils/MouseCursor.cpp @@ -0,0 +1,199 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// WIN32 VERSION + +//============================================================================= +// Prefix +//============================================================================= +#include "stdafx.h" + +//============================================================================= +// Includes +//============================================================================= +#include "MouseCursor.h" +#include <QPixmap> +#include <QDebug> + +//#ifdef WIN32 +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ARROW = 0; // IDC_ARROW +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_WAIT = 1; // IDC_WAIT +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_LEFTRIGHT = 2; // IDC_SIZEWE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_RESIZE_UPDOWN = 3; // IDC_SIZENS +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_MOVE = 4; // IDC_GROUP_MOVE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_ROTATE = 5; // IDC_GROUP_ROTATE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_GROUP_SCALE = 6; // IDC_GROUP_SCALE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_MOVE = 7; // IDC_ITEM_MOVE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_ROTATE = 8; // IDC_ITEM_ROTATE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_ITEM_SCALE = 9; // IDC_ITEM_SCALE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_PAN = + 10; // IDC_EDIT_CAMERA_PAN +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ROTATE = + 11; // IDC_EDIT_CAMERA_ROTATE +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_EDIT_CAMERA_ZOOM = + 12; // IDC_EDIT_CAMERA_ZOOM +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_BLANK = 13; // blank cursor +const CMouseCursor::TUICMouseCursor CMouseCursor::CURSOR_IBEAM = 14; + +//============================================================================= +/** + * Constructor + */ +CMouseCursor::CMouseCursor() + : m_IsThemeCursor(false) + , m_ThemeCursor(-1) +{ +} + +//============================================================================= +/** + * Destructor + */ +CMouseCursor::~CMouseCursor() +{ + Destroy(); +} + +//============================================================================= +/** + * @return A platform-specific handle to the cursor, or nullptr if no cursor has been loaded + */ +QCursor CMouseCursor::GetHandle() +{ + return m_Handle; +} + +//============================================================================= +/** + * If a cursor has been loaded, this function will change the current cursor + * to the newly loaded one. + */ +void CMouseCursor::Show() +{ + qWarning() << Q_FUNC_INFO << "QCursor doesn't work this way - set a breakpoint and debug caller"; +} + +//============================================================================= +/** +* Sets the cursor position +* @param inXPos x position of the cursor (in pixels) +* @param inYPos y position of the cursor (in pixels) +*/ +void CMouseCursor::SetCursorPos(long inXPos, long inYPos) +{ + QCursor::setPos(QPoint(inXPos, inYPos)); +} + +//============================================================================= +/** + * Releases the cursor if one has been loaded. Called by the destructor. + * WINDOWS IMPLEMENTATION + */ +void CMouseCursor::Destroy() +{ +} + +//============================================================================= +/** + * Loads the specified cursor resource. All cursors are expected to be + * resources that are loaded from ".cur" files. Some standard cursors are + * defined by the system and can be found in the MSDN (IDC_ARROW for example). + * WINDOWS IMPLEMENTATION + * + * @param inCursor ID of the cursor to be loaded + * @return true if the cursor was successfully loaded, otherwise false + */ +bool CMouseCursor::Load(TUICMouseCursor inCursor) +{ + // Convert from our cursors to Windows specific cursors + switch (inCursor) { + case CURSOR_ARROW: + m_Handle = Qt::ArrowCursor; + break; + + case CURSOR_WAIT: + m_Handle = Qt::WaitCursor; + break; + + case CURSOR_RESIZE_LEFTRIGHT: + m_Handle = Qt::SizeHorCursor; + break; + + case CURSOR_RESIZE_UPDOWN: + m_Handle = Qt::SizeVerCursor; + break; + + case CURSOR_GROUP_MOVE: + m_Handle = QCursor(QPixmap(":/cursors/group_move.png"), 0, 0); + break; + + case CURSOR_GROUP_ROTATE: + m_Handle = QCursor(QPixmap(":/cursors/group_rotate.png"), 0, 0); + break; + + case CURSOR_GROUP_SCALE: + m_Handle = QCursor(QPixmap(":/cursors/group_scale.png"), 0, 0); + break; + + case CURSOR_ITEM_MOVE: + m_Handle = QCursor(QPixmap(":/cursors/item_move.png"), 0, 0); + break; + + case CURSOR_ITEM_ROTATE: + m_Handle = QCursor(QPixmap(":/cursors/item_rotate.png"), 0, 0); + break; + + case CURSOR_ITEM_SCALE: + m_Handle = QCursor(QPixmap(":/cursors/item_scale.png"), 0, 0); + break; + + case CURSOR_EDIT_CAMERA_PAN: + m_Handle = QCursor(QPixmap(":/cursors/edit_camera_pan.png"), 10, 10); + break; + + case CURSOR_EDIT_CAMERA_ROTATE: + m_Handle = QCursor(QPixmap(":/cursors/edit_camera_rot.png"), 8, 10); + break; + + case CURSOR_EDIT_CAMERA_ZOOM: + m_Handle = QCursor(QPixmap(":/cursors/edit_camera_zoom.png"), 8, 8); + break; + + case CURSOR_BLANK: + m_Handle = Qt::BlankCursor; + break; + case CURSOR_IBEAM: + m_Handle = Qt::IBeamCursor; + break; + default: + m_Handle = QCursor(); + break; + } + return true; +} diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.cpp b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp new file mode 100644 index 00000000..e159fa12 --- /dev/null +++ b/src/Authoring/Studio/_Win/Utils/WinUtils.cpp @@ -0,0 +1,600 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "stdafx.h" +#include "Strings.h" + +#include "WinUtils.h" + +//============================================================================== +/** + * DrawBitmap + * + * Draw a bitmap given a device context, position and HBITMAP handle. + * + * @param inDC Device context for drawing + * @param inPos CPoint position for drawing + * @param inBitmap Handle of the bitmap to draw + */ +//============================================================================== +void CWinUtils::DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap) +{ + CDC theMemDC; + BITMAP theBitmapStruct; + CBitmap *theOldBitmap; + + if ((inDC != nullptr) && (inBitmap != nullptr)) { + GetObject(inBitmap, sizeof(BITMAP), &theBitmapStruct); + + theMemDC.CreateCompatibleDC(inDC); + theOldBitmap = theMemDC.SelectObject(CBitmap::FromHandle(inBitmap)); + + inDC->BitBlt(inPos.x, inPos.y, theBitmapStruct.bmWidth, theBitmapStruct.bmHeight, &theMemDC, + 0, 0, SRCCOPY); + + theMemDC.SelectObject(theOldBitmap); + theMemDC.DeleteDC(); + } +} + +//============================================================================== +/** + * DrawTransparentBitmap + * + * Draw a bitmap given a device context, position and HBITMAP handle using transparency + * + * @param inDC Device context for drawing + * @param inDestX Destination X position + * @param inDestY Destination Y position + * @param inBmp Bitmap for drawing + * @param inColorTransparent Transparent color + * @param inWidth Destination width + * @param inHeight Destination height + * @param inSourceX Source X position + * @param inSourceY Source Y position + */ +//============================================================================== +void CWinUtils::DrawTransparentBitmap(CDC *inDC, long inDestX, long inDestY, HBITMAP inBmp, + COLORREF inColorTransparent, long inWidth, long inHeight, + long inSourceX, long inSourceY) +{ + CDC theMemDC; + BITMAP theBitmap; + CBitmap *theOldBmp; + + GetObject(inBmp, sizeof(BITMAP), &theBitmap); + + if (inWidth == -1) + inWidth = theBitmap.bmWidth; + if (inHeight == -1) + inHeight = theBitmap.bmHeight; + + theMemDC.CreateCompatibleDC(inDC); + theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp)); + + TransparentBltExt(inDC->m_hDC, inDestX, inDestY, inWidth, inHeight, theMemDC.m_hDC, inSourceX, + inSourceY, inWidth, inHeight, inColorTransparent); + + theMemDC.SelectObject(theOldBmp); + theMemDC.DeleteDC(); +} + +//============================================================================== +/** + * TransparentBltExt + * + * Draw a bitmap given a device context, position and HBITMAP handle using transparency + * + * @param inDC Device context for drawing + * @param inDestX Destination X position + * @param inDestY Destination Y position + * @param inBmp Bitmap for drawing + * @param inColorTransparent Transparent color + * @param inWidth Destination width + * @param inHeight Destination height + * @param inSourceX Source X position + * @param inSourceY Source Y position + */ +//============================================================================== +BOOL CWinUtils::TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest, + long inWidthDest, long inHeightDest, HDC inDCSrc, + long inXOriginSrc, long inYOriginSrc, long inWidthSrc, + long inHeightSrc, UINT inColorTransparent) +{ + if ((inWidthDest < 1) || (inWidthSrc < 1) || (inHeightDest < 1) || (inHeightSrc < 1)) + return FALSE; + + HDC theDC, theMaskDC; + HDC theNewMaskDC; + HBITMAP theBmp, theOldBmp, theMaskBmp, theOldMask; + HBITMAP theNewMask; + + theDC = CreateCompatibleDC(nullptr); + theBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, GetDeviceCaps(theDC, BITSPIXEL), nullptr); + + if (theBmp == nullptr) { + DeleteDC(theDC); + return FALSE; + } + + theOldBmp = (HBITMAP)SelectObject(theDC, theBmp); + + if (!BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, inDCSrc, inXOriginSrc, inYOriginSrc, + SRCCOPY)) { + SelectObject(theDC, theOldBmp); + DeleteObject(theBmp); + DeleteDC(theDC); + return FALSE; + } + + theMaskDC = CreateCompatibleDC(nullptr); + theMaskBmp = CreateBitmap(inWidthSrc, inHeightSrc, 1, 1, nullptr); + + if (theMaskBmp == nullptr) { + SelectObject(theDC, theOldBmp); + DeleteObject(theBmp); + DeleteDC(theDC); + DeleteDC(theMaskDC); + return FALSE; + } + + theOldMask = (HBITMAP)SelectObject(theMaskDC, theMaskBmp); + SetBkColor(theMaskDC, RGB(0x00, 0x00, 0x00)); + SetTextColor(theMaskDC, RGB(0xFF, 0xFF, 0xFF)); + + if (!BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, nullptr, 0, 0, BLACKNESS)) { + SelectObject(theMaskDC, theOldMask); + DeleteObject(theMaskBmp); + DeleteDC(theMaskDC); + SelectObject(theDC, theOldBmp); + DeleteObject(theBmp); + DeleteDC(theDC); + return FALSE; + } + + SetBkColor(theDC, inColorTransparent); + BitBlt(theMaskDC, 0, 0, inWidthSrc, inHeightSrc, theDC, 0, 0, SRCINVERT); + + SetBkColor(theDC, RGB(0x00, 0x00, 0x00)); + SetTextColor(theDC, RGB(0xFF, 0xFF, 0xFF)); + BitBlt(theDC, 0, 0, inWidthSrc, inHeightSrc, theMaskDC, 0, 0, SRCAND); + + theNewMaskDC = CreateCompatibleDC(nullptr); + theNewMask = + CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr); + if (theNewMask == nullptr) { + SelectObject(theDC, theOldBmp); + DeleteDC(theDC); + SelectObject(theMaskDC, theOldMask); + DeleteDC(theMaskDC); + DeleteDC(theNewMaskDC); + DeleteObject(theBmp); + DeleteObject(theMaskBmp); + return FALSE; + } + + SetStretchBltMode(theNewMaskDC, COLORONCOLOR); + HBITMAP theOldNewMask = (HBITMAP)SelectObject(theNewMaskDC, theNewMask); + StretchBlt(theNewMaskDC, 0, 0, inWidthDest, inHeightDest, theMaskDC, 0, 0, inWidthSrc, + inHeightSrc, SRCCOPY); + + SelectObject(theMaskDC, theOldMask); + DeleteDC(theMaskDC); + DeleteObject(theMaskBmp); + + HDC theNewImageDC = CreateCompatibleDC(nullptr); + HBITMAP theNewImage = + CreateBitmap(inWidthDest, inHeightDest, 1, GetDeviceCaps(theNewMaskDC, BITSPIXEL), nullptr); + if (theNewImage == nullptr) { + SelectObject(theDC, theOldBmp); + DeleteDC(theDC); + DeleteDC(theNewMaskDC); + DeleteObject(theBmp); + return FALSE; + } + + HBITMAP theOldNewImage = (HBITMAP)SelectObject(theNewImageDC, theNewImage); + StretchBlt(theNewImageDC, 0, 0, inWidthDest, inHeightDest, theDC, 0, 0, inWidthSrc, inHeightSrc, + SRCCOPY); + + SelectObject(theDC, theOldBmp); + DeleteDC(theDC); + DeleteObject(theBmp); + + // Finally, do the final blitting to get the image to the destination device context. + BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewMaskDC, 0, 0, + SRCAND); + BitBlt(inDCDest, inXOriginDest, inYOriginDest, inWidthDest, inHeightDest, theNewImageDC, 0, 0, + SRCPAINT); + + SelectObject(theNewImageDC, theOldNewImage); + DeleteDC(theNewImageDC); + SelectObject(theNewMaskDC, theOldNewMask); + DeleteDC(theNewMaskDC); + DeleteObject(theNewImage); + DeleteObject(theNewMask); + + return TRUE; +} + +//============================================================================== +/** + * DrawAlphaBlendBitmap + * + * Draw a bitmap given a device context, position and HBITMAP handle using + * alpha blending and transparency. + * + * @param inDC Device context for drawing + * @param inDestX Destination X position + * @param inDestY Destination Y position + * @param inBmp Bitmap for drawing + * @param inColorTransparent Transparent color + * @param inWidth Destination width + * @param inHeight Destination height + * @param inSourceX Source X position + * @param inSourceY Source Y position + */ +//============================================================================== +void CWinUtils::DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp, + short inWidth, short inHeight, short inSourceX, + short inSourceY, short inAlpha, BOOL inTransparentFlag, + COLORREF inColorTransparent) +{ + Q_UNUSED(inColorTransparent); + + CDC theMemDC; + BITMAP theBitmap; + CBitmap *theOldBmp; + short theWidth = inWidth; + short theHeight = inHeight; + + COLORREF theBackColor; + + // Get the size of the bitmap. + GetObject(inBmp, sizeof(BITMAP), &theBitmap); + + if (inWidth == -1) + theWidth = (short)theBitmap.bmWidth; + if (inHeight == -1) + theHeight = (short)theBitmap.bmHeight; + + theMemDC.CreateCompatibleDC(inDC); + theOldBmp = theMemDC.SelectObject(CBitmap::FromHandle(inBmp)); + + if (inTransparentFlag) { + // Get the current background pixel at 0,0 + theBackColor = theMemDC.GetPixel(0, 0); + + // Create a fill brush and select into the device context + CBrush theFillBrush(inColorTransparent); + CBrush *theOldFillBrush; + + // Fill to replace the existing background color with the replacement color. + theOldFillBrush = theMemDC.SelectObject(&theFillBrush); + theMemDC.ExtFloodFill(0, 0, theBackColor, FLOODFILLSURFACE); + theMemDC.ExtFloodFill(theWidth - 1, 0, theBackColor, FLOODFILLSURFACE); + theMemDC.ExtFloodFill(theWidth - 1, theHeight - 1, theBackColor, FLOODFILLSURFACE); + theMemDC.ExtFloodFill(0, theHeight - 1, theBackColor, FLOODFILLSURFACE); + theMemDC.SelectObject(theOldFillBrush); + } + + // Draw the alpha-blended image. + AlphaBlendExt(inDC->m_hDC, inDestX, inDestY, theWidth, theHeight, theMemDC.m_hDC, inSourceX, + inSourceY, theWidth, theHeight, inAlpha); + + theMemDC.SelectObject(theOldBmp); + theMemDC.DeleteDC(); +} + +//============================================================================== +/** + * AlphaBlendExt + * + * Draws a bitmap using alpha blending. Works in NT/2000/9x + * + * @param inDCDest Destination device context + * @param inX X coordinate for drawing + * @param inY Y coordinate for drawing + * @param inWidth Drawing width + * @param inHeight Drawing height + * @param inDCSrc Source device context + * @param inSourceX X source coordinate + * @param inSourceY Y source coordinate + * @param inSourceWidth Source drawing width + * @param inSourceHeight Source drawing height + * @param inAlpha Alpha blend: 0-255, where 255 is opaque + */ +//============================================================================== +BOOL CWinUtils::AlphaBlendExt(HDC inDCDest, short inX, short inY, short inWidth, short inHeight, + HDC inDCSrc, short inSourceX, short inSourceY, short inSourceWidth, + short inSourceHeight, short inAlpha) +{ + BITMAPINFOHEADER theBMI; + + theBMI.biSize = sizeof(BITMAPINFOHEADER); + theBMI.biWidth = inWidth; + theBMI.biHeight = inHeight; + theBMI.biPlanes = 1; + theBMI.biBitCount = 32; // 24 bits + alpha channel + theBMI.biCompression = BI_RGB; // no compression + theBMI.biSizeImage = 0; + theBMI.biXPelsPerMeter = 0; + theBMI.biYPelsPerMeter = 0; + theBMI.biClrUsed = 0; // use the whole palette + theBMI.biClrImportant = 0; + + BYTE *theSrcBits; + HBITMAP theBmpSrc; + + // Create DIB section in shared memory + theBmpSrc = CreateDIBSection(inDCSrc, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS, + (void **)&theSrcBits, 0, 0L); + + BYTE *theDestBits; + HBITMAP theBmpDest; + + // Create DIB section in shared memory + theBmpDest = CreateDIBSection(inDCDest, (BITMAPINFO *)&theBMI, DIB_RGB_COLORS, + (void **)&theDestBits, 0, 0L); + + // Copy our source and destination bitmaps onto our DIBSections. + // so we can get access to their bits using the BYTE*'s we used + // in the CreateDIBSection()s above. + + HDC theDC = CreateCompatibleDC(nullptr); + HBITMAP theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc); + + if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCSrc, inSourceX, inSourceY, inSourceWidth, + inSourceHeight, SRCCOPY)) { + SelectObject(theDC, theDCOld); + DeleteDC(theDC); + DeleteObject(theBmpSrc); + DeleteObject(theBmpDest); + return FALSE; + } + + SelectObject(theDC, theBmpDest); + + if (!StretchBlt(theDC, 0, 0, inWidth, inHeight, inDCDest, inX, inY, inWidth, inHeight, + SRCCOPY)) { + SelectObject(theDC, theDCOld); + DeleteDC(theDC); + DeleteObject(theBmpSrc); + DeleteObject(theBmpDest); + return FALSE; + } + + SelectObject(theDC, theDCOld); + DeleteDC(theDC); + + short theXLoop, theYLoop; + + for (theYLoop = 0; theYLoop < inHeight; ++theYLoop) { + LPBYTE theDestRGB = (LPBYTE) & ((DWORD *)theDestBits)[theYLoop * inWidth]; + LPBYTE theSrcRGB = (LPBYTE) & ((DWORD *)theSrcBits)[theYLoop * inWidth]; + + for (theXLoop = 0; theXLoop < inWidth; theXLoop++) { + theSrcRGB[0] = (BYTE)((theDestRGB[0] * (255 - inAlpha) + theSrcRGB[0] * inAlpha) >> 8); + theSrcRGB[1] = (BYTE)((theDestRGB[1] * (255 - inAlpha) + theSrcRGB[1] * inAlpha) >> 8); + theSrcRGB[2] = (BYTE)((theDestRGB[2] * (255 - inAlpha) + theSrcRGB[2] * inAlpha) >> 8); + + theSrcRGB += 4; + theDestRGB += 4; + } + } + + theDC = CreateCompatibleDC(nullptr); + + theDCOld = (HBITMAP)SelectObject(theDC, theBmpSrc); + + if (!BitBlt(inDCDest, inX, inY, inWidth, inHeight, theDC, 0, 0, SRCCOPY)) { + SelectObject(theDC, theDCOld); + DeleteDC(theDC); + DeleteObject(theBmpSrc); + DeleteObject(theBmpDest); + return FALSE; + } + + SelectObject(theDC, theDCOld); + DeleteDC(theDC); + + DeleteObject(theBmpSrc); + DeleteObject(theBmpDest); + + return TRUE; +} + +//============================================================================== +/** + * GetStudioLogFont: Fill a LOGFONT structure with the default font information for Studio + *objects. + * + * Create a LOGFONT structure with data used by the various palettes and controls in Studio. + * + * @param outLogFont LOGFONT structure returned by this function. + */ +//============================================================================== +void CWinUtils::GetStudioLogFont(LOGFONT &outLogFont) +{ + // Create the default Studio font - specified in string table so that it can be changed for + // different languages + memset(&outLogFont, 0, sizeof(LOGFONT)); + CString theFontSize = ::LoadResourceString(IDS_STUDIOFONT_SIZE); + CString theFontFace = L"SegoeUI"; + outLogFont.lfHeight = _wtoi(theFontSize); + wcscpy(outLogFont.lfFaceName, theFontFace); + // Make sure that you set the character set to the system default or your strings won't be + // localizable + outLogFont.lfCharSet = DEFAULT_CHARSET; +} + +//============================================================================= +/** + * Copy the contents of a File into an Archive. + * This will read the entire file into the archive. + * The file should exist already. + * @param inFilename the name of the file to read in. + * @param inDestination the destination archive for the data. + */ +//============================================================================= +void CWinUtils::CopyFileToArchive(CString inFilename, CArchive &inDestination) +{ + CFile theFile(inFilename, CFile::modeRead); + + unsigned long theLength = (unsigned long)theFile.GetLength(); + unsigned long theBufferSize = 1024; + while (theBufferSize < theLength / 10 && theBufferSize < 1e6) + theBufferSize *= 2; // double until we have a buffer that is about %10 of file size + char *theBuffer = new char[theBufferSize]; + + unsigned long theReadCount = theBufferSize; + unsigned long theTotalReadCount = 0; + + // Loop around reading the file in chunks + while (theTotalReadCount < theLength) { + if (theLength - theTotalReadCount < theReadCount) + theReadCount = theLength - theTotalReadCount; + + theFile.Read(theBuffer, theReadCount); + inDestination.Write(theBuffer, theReadCount); + + theTotalReadCount += theReadCount; + } + + theFile.Close(); + delete[] theBuffer; +} + +//============================================================================= +/** + * Copy the contents of an Archive into a File. + * If the file does not exist it will be created. If it does exist it will be + * cleared. + * @param inArchive the source of the data for the file. + * @param inDestination the file the data is to be written to. + * @param inLength the amount of data to copy to the file. + */ +//============================================================================= +void CWinUtils::CopyArchiveToFile(CArchive &inArchive, CString inDestination, + unsigned long inLength) +{ + CFile theFile(inDestination, CFile::modeWrite | CFile::modeCreate); + + unsigned long theBufferSize = 1024; + while (theBufferSize < inLength / 10 && theBufferSize < 1e6) + theBufferSize *= 2; // double until we have a buffer that is about %10 of file size + char *theBuffer = new char[theBufferSize]; + + unsigned long theLength = inLength; + unsigned long theReadCount = theBufferSize; + unsigned long theTotalReadCount = 0; + + // Loop around reading from the archive and writing to the file. + while (theTotalReadCount < theLength) { + if (theLength - theTotalReadCount < theReadCount) + theReadCount = theLength - theTotalReadCount; + + inArchive.Read(theBuffer, theReadCount); + theFile.Write(theBuffer, theReadCount); + + theTotalReadCount += theReadCount; + } + theFile.Close(); + delete[] theBuffer; +} + +//============================================================================= +/** + * Used for StringToInt64 to avoid double errors in math.h's pow( ). + * + * @param inNumber Base number + * @param inPower Power to raise the base + * + * @return Result of x^y + */ +//============================================================================= +unsigned __int64 CWinUtils::RaisePower(unsigned __int64 inNumber, unsigned long inPower) +{ + if (inPower == 0) + return 1; + return inNumber * RaisePower(inNumber, inPower - 1); +} + +//============================================================================= +/** + * Parse the string into an __int64. + * + * @param inString the string to parse. + * @param inStringLen the length of the string. + * @param inBase the base of the character encoding (16 is Hex, 10 is decimal). + * + * @return <the parsed string. + */ +//============================================================================= +unsigned __int64 CWinUtils::StringToInt64(const char *inString, unsigned short inStringLen, + unsigned short inBase) +{ + unsigned __int64 theKey = 0; + char theChar; + unsigned short i; + + for (i = 0; i < inStringLen; ++i) { + theChar = inString[i]; + if (theChar < 'A') + theChar -= '0'; + else if (theChar < 'a') + theChar -= 'A' - 10; + else + theChar -= 'a' - 10; + + theKey += + ((unsigned __int64)theChar) * (unsigned __int64)RaisePower(inBase, inStringLen - 1 - i); + } + return theKey; +} + +//============================================================================= +/** + * Get a wchar_t from an MFC CString (used to go to Q3DStudio::CString without flattening unicode) + * + * @param inMFCString the string convert + * + * @return <the null-terminated wchar_t buffer. caller must delete[]!!!! + */ +//============================================================================= +wchar_t *CWinUtils::WideFromMFC(::CString inMFCString) +{ + TCHAR *theBuffer = inMFCString.GetBuffer(0); + long theMultiLength = inMFCString.GetLength(); + wchar_t *theDestBuffer = new wchar_t[theMultiLength * 2 + 1]; // times 2 so we know we are big + // enough for 1 and 2 byte chars + // from multibyte + wcscpy(theDestBuffer, theBuffer); + inMFCString.ReleaseBuffer(); + return theDestBuffer; +}
\ No newline at end of file diff --git a/src/Authoring/Studio/_Win/Utils/WinUtils.h b/src/Authoring/Studio/_Win/Utils/WinUtils.h new file mode 100644 index 00000000..121a61bd --- /dev/null +++ b/src/Authoring/Studio/_Win/Utils/WinUtils.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDED_WIN_UTILS_H +#define INCLUDED_WIN_UTILS_H 1 + +#pragma once + +class CWinUtils +{ +public: + static BOOL AlphaBlendExt(HDC hDCDest, short x, short y, short cx, short cy, HDC hDCSrc, + short sx, short sy, short sw, short sh, short inAlpha); + static void DrawAlphaBlendBitmap(CDC *inDC, short inDestX, short inDestY, HBITMAP inBmp, + short inWidth, short inHeight, short inSourceX, + short inSourceY, short inAlpha, BOOL inTransparentFlag = FALSE, + COLORREF inColorTransparent = RGB(0x00, 0x00, 0x00)); + static void DrawBitmap(CDC *inDC, CPoint inPos, HBITMAP inBitmap); + static void DrawTransparentBitmap(CDC *pDC, long x, long y, HBITMAP hBmp, + COLORREF colorTransparent, long w = -1, long h = -1, + long sx = 0, long sy = 0); + static BOOL TransparentBltExt(HDC inDCDest, long inXOriginDest, long inYOriginDest, + long inWidthDest, long inHeightDest, HDC inDCSrc, + long inXOriginSrc, long inYOriginSrc, long inWidthSrc, + long inHeightSrc, UINT inColorTransparent); + + static void GetStudioLogFont(LOGFONT &outLogFont); + static unsigned __int64 StringToInt64(const char *inString, unsigned short inStringLen, + unsigned short inBase); + static void CopyFileToArchive(CString inFilename, CArchive &inDestination); + static void CopyArchiveToFile(CArchive &inArchive, CString inDestination, + unsigned long inLength); + static wchar_t *WideFromMFC(::CString inMFCString); + +protected: + static unsigned __int64 RaisePower(unsigned __int64 inNumber, unsigned long inPower); +}; + +#endif // INCLUDED_WIN_UTILS_H diff --git a/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp new file mode 100644 index 00000000..517aed97 --- /dev/null +++ b/src/Authoring/Studio/_Win/Workspace/Dialogs.cpp @@ -0,0 +1,1332 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "stdafx.h" +#include "qtAuthoring-config.h" +#include "Strings.h" +#include "StringLoader.h" + +#include "Dialogs.h" +#include "StudioApp.h" +#include "Doc.h" + +#include "InterpolationDlg.h" + +#ifdef KDAB_TEMPORARILY_REMOVED +#include "UICMessageBox.h" +#include "StringTokenizer.h" +#include "Resource.h" +#include "Preferences.h" +#include "ProgressPalette.h" +#include "ProgressView.h" +#include "Views.h" +#include "WinUtils.h" +#include "MasterP.h" +#include "TimeEditDlg.h" +#include "StudioPreferences.h" +#include "ResetKeyframeValuesDlg.h" +#include "GLVersionDlg.h" +#endif +#include "Core.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "UICMacros.h" +#include "IDocumentEditor.h" +#include "UICFileTools.h" +#endif +#include "ImportUtils.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "FileDialogEx.h" +#endif + +#include "StringLoader.h" + +#include <QFileDialog> +#include <QMessageBox> +#include <QStandardPaths> + +#include <iostream> + +//============================================================================= +/** + * Constructor + * @param inShowGUI true if dialogs should be displayed or piped to std:cout instead + */ +CDialogs::CDialogs(bool inShowGUI /*= true*/) +#ifdef KDAB_TEMPORARILY_REMOVED + : m_ProgressPalette(nullptr) + , m_ShowGUI(inShowGUI) + , m_LastSaveFile(CUICFile::GetApplicationDirectory().GetAbsolutePath()) +#endif +{ +} + +//============================================================================= +/** + * Destructor + */ +CDialogs::~CDialogs() +{ +} + +//============================================================================= +/** + * Displays a multiline text edit. + * @param ioText + * @param inNotification + */ +#if 0 +void CDialogs::DisplayMultilineTextEdit(Q3DStudio::CString &ioText, + CMultilineEditDlg::INotification *inNotifiction) +{ + CRct theLocation = CStudioPreferences::GetMultilineTextLocation(); + + CMultilineEditDlg theMultilineEditDlg(inNotifiction, theLocation); + theMultilineEditDlg.SetString(ioText); + if (theMultilineEditDlg.DoModal() == IDOK) { + // Set the string + ioText = theMultilineEditDlg.GetString(); + + // Save the window position + theLocation = theMultilineEditDlg.GetLocation(); + CStudioPreferences::SetMultilineTextLocation(theLocation); + } +} +#endif + +//============================================================================= +/** + * Displays a dialog asking the user to choose the keyframe interpolation. + * + * @param ioEaseIn value to be set as the ease in default - passes back the value chosen by the user + * @param ioEaseOut value to be set as the ease out default - passes back the value chosen by the + * user + * @return true if the user clicked OK on the dialog (indicating that the values should be updated + * on the track) + */ +bool CDialogs::PromptForKeyframeInterpolation(float &ioEaseIn, float &ioEaseOut) +{ + bool theReturnValue = false; + + CInterpolationDlg theInterpolationDialog; + theInterpolationDialog.setEaseIn(ioEaseIn); + theInterpolationDialog.setEaseOut(ioEaseOut); + + // If the user presses the OK button + if (theInterpolationDialog.exec() == QDialog::Accepted) { + // Retrieve the new interpolation values + ioEaseIn = theInterpolationDialog.easeIn(); + ioEaseOut = theInterpolationDialog.easeOut(); + theReturnValue = true; + } + + return theReturnValue; +} + +//============================================================================= +/** + * Notify the user that the deletion of an asset has failed. + */ +void CDialogs::DisplayAssetDeleteFailed() +{ + Q3DStudio::CString theMessage = + ::LoadResourceString(IDS_ERROR_CLIENTSAVE); // TODO: Should display the correct string + Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_MSGTITLE); + + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl; + } +} + +//============================================================================= +/** + * Get the export choice. + */ +CUICFile CDialogs::GetExportChoice(const Q3DStudio::CString &, const Q3DStudio::CString &) +{ + // Need to fix this for windows if we decide to use it + return CUICFile("", false, false); +} + +//============================================================================== +/** + * Notify that we are unable to refresh the resource. + */ +void CDialogs::DisplayRefreshResourceFailed(const Q3DStudio::CString &inResourceName, + const Q3DStudio::CString &inDescription) +{ + Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETITLE)); + + Q3DStudio::CString theText; + theText.Format(::LoadResourceString(IDS_ERROR_REFRESHRESOURCETEXT), + static_cast<const wchar_t *>(inResourceName)); + + if (!inDescription.IsEmpty()) + theText += inDescription; + + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theText, CUICMessageBox::ICON_WARNING, false, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << theText.GetCharStar() << std::endl << std::endl; + } +} + +//============================================================================= +/** + * Notify the user that the loading of the requested resource failed. + * + * Possible failed import messages are: + * IDS_ERROR_IMPORTLUARESOURCETEXT - Sorry - Studio was unable to + *import the LUA script.\nPlease check the file and try again.\nNote that LUA files must be + *syntactically correct to be importable. + * IDS_ERROR_IMPORTRESOURCETEXT - Sorry - Studio was unable to + *import the resource.\nPlease check the above file and try again. + * IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT - Sorry - Studio was unable to import + *the resource file.\nThis resource file type is not currently supported by Studio.\n + * + * @param inURL the URL for the asset that was to have been imported + * @param inErrorDescription description for the failure, if any + * @param inWarningsOnly not a failure, just warnings + */ +void CDialogs::DisplayImportFailed(const QUrl &inURL, const QString &inDescription, + bool inWarningsOnly) +{ + // Notify the user we couldn't load the resource. + Q3DStudio::CString theTitle, theText, theMsgText; + + theTitle = ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE); + // specify if its an error or warning + theTitle = (!inWarningsOnly) ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_ERROR) + : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETITLE_WARNING); + + // Determine the asset type + EStudioObjectType theAssetType = + Q3DStudio::ImportUtils::GetObjectFileTypeForFile(inURL.path(), false) + .m_ObjectType; + + bool theIsStudioObject = theAssetType != OBJTYPE_UNKNOWN; + + // Is this a LUA file, but perhaps incorrectly formatted? + if (theAssetType == OBJTYPE_BEHAVIOR) { + // Load the message about the LUA format + if (inWarningsOnly) + theText = ::LoadResourceString(IDS_WARNING_IMPORTLUARESOURCETEXT); + else + theText = ::LoadResourceString(IDS_ERROR_IMPORTLUARESOURCETEXT); + if (!inDescription.isEmpty()) { + theText += L"\n"; + theText += Q3DStudio::CString::fromQString(inDescription); + } + } else if (theAssetType != OBJTYPE_UNKNOWN || theIsStudioObject) { + // Valid registered file type, but invalid file + + bool theNoDescription = inDescription.isEmpty(); + // Load default text stating that the import resource failed. + // descriptions if present are presented as "reasons" for failure. + if (!inWarningsOnly || theNoDescription) { + theText.Format(::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT), theNoDescription + ? L"." + : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_REASON).c_str()); + theText += "\n"; + } + if (!theNoDescription) + theText += Q3DStudio::CString::fromQString(inDescription); + else + theText += ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_CHECKFILE); + } else { + // Display the warning messsage if we have one + // instead of a meaningless message. This provides more feed back + if (!inDescription.isEmpty()) + theText += Q3DStudio::CString::fromQString(inDescription); + else + theText = ::LoadResourceString( + IDS_ERROR_IMPORTUNSUPPORTEDRESOURCETYPETEXT); // Load default text stating that the + // import resource failed. + } + + Q3DStudio::CString theFormatString( + !inWarningsOnly ? ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_FAILED) + : ::LoadResourceString(IDS_ERROR_IMPORTRESOURCETEXT_COMPLETEWITHWARNING)); + theFormatString += _UIC("\n%ls\n\n"); + std::wstring wstr = inURL.path().toStdWString(); + theMsgText.Format(theFormatString, static_cast<const wchar_t *>(wstr.c_str())); + theMsgText += theText; + + // Display the failed import resource message. + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theMsgText, CUICMessageBox::ICON_WARNING, false, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << theMsgText.GetCharStar() << std::endl; + } +} + +namespace { + +inline Q3DStudio::CString CreateExtensionsList(const char **extList) +{ + Q3DStudio::CString retval; + for (const char **ext = extList; *ext != nullptr; ++ext) { + if (retval.Length()) + retval += " "; + retval += Q3DStudio::CString("*.") + *ext; + } + return retval; +} + +struct SAllowedTypesEntry +{ + Q3DStudio::DocumentEditorFileType::Enum m_FileType; + long m_ResourceStringId; // Model Files, Image Files, etc + const char **m_FileExtensions; +}; +const char *imgExts[] = { + "png", "jpg", "jpeg", "dds", "bmp", "gif", "hdr", nullptr, +}; +const wchar_t *wideImgExts[] = { + L"png", L"jpg", L"jpeg", L"dds", L"bmp", L"gif", L"hdr", nullptr, +}; +const char *modelExts[] = { + CDialogs::GetDAEFileExtension(), +#ifdef QT_3DSTUDIO_FBX + CDialogs::GetFbxFileExtension(), +#endif + // TODO CDialogs::GetImportFileExtension(), + // TODO CDialogs::GetMeshFileExtension(), + nullptr, +}; +const char *meshExts[] = { + CDialogs::GetMeshFileExtension(), nullptr, +}; +const char *importExts[] = { + CDialogs::GetImportFileExtension(), nullptr, +}; +const char *behaviorExts[] = { + CDialogs::GetLUAFileExtension(), nullptr, +}; +const char *fontExts[] = { + "ttf", "otf", nullptr, +}; +const wchar_t *wideFontExts[] = { + L"ttf", L"otf", nullptr, +}; +const char *effectExts[] = { + "effect", nullptr, +}; +const wchar_t *wideEffectExts[] = { + L"effect", nullptr, +}; +const char *materialExts[] = { + "material", nullptr, +}; +const wchar_t *wideMaterialExts[] = { + L"material", nullptr, +}; +const char *soundExts[] = { + "wav", nullptr, +}; +const wchar_t *wideSoundExts[] = { + L"wav", nullptr, +}; + +// List of file types allowed during import +SAllowedTypesEntry g_AllowedImportTypes[] = { + { Q3DStudio::DocumentEditorFileType::DAE, IDS_LIBRARYIMPORT_MODEL, modelExts }, +#ifdef QT_3DSTUDIO_FBX + { Q3DStudio::DocumentEditorFileType::FBX, IDS_LIBRARYIMPORT_MODEL, modelExts }, +#endif +}; +size_t g_NumAllowedImportTypes = sizeof(g_AllowedImportTypes) / sizeof(*g_AllowedImportTypes); + +// List of file types allowed for file references +SAllowedTypesEntry g_AllowedFileReferencesTypes[] = { + { Q3DStudio::DocumentEditorFileType::Image, IDS_LIBRARYIMPORT_IMAGE, imgExts }, + { Q3DStudio::DocumentEditorFileType::Behavior, IDS_LIBRARYIMPORT_BEHAVIOR, behaviorExts }, + { Q3DStudio::DocumentEditorFileType::Mesh, IDS_LIBRARYIMPORT_MESH, meshExts }, + { Q3DStudio::DocumentEditorFileType::Import, IDS_LIBRARYIMPORT_IMPORT, importExts }, + { Q3DStudio::DocumentEditorFileType::Effect, IDS_LIBRARYIMPORT_EFFECT, effectExts }, +}; +size_t g_NumAllowedFileReferencesTypes = + sizeof(g_AllowedFileReferencesTypes) / sizeof(*g_AllowedFileReferencesTypes); +} + +QString CDialogs::ConfirmRefreshModelFile(const QString &inFile) +{ + // this produces an extension string which contains all allowed formats specified in + // g_AllowedImportTypes + // currently DAE and FBX + QString theFileFilter = + CreateAllowedTypesString(Q3DStudio::DocumentEditorFileType::DAE, true); + + + return QFileDialog::getOpenFileName(qApp->activeWindow(), QObject::tr("Open"), + inFile, theFileFilter); +} + +//============================================================================== +/** + * Allows the user to select/confirm the file to fix broken file reference. + * This method opens a file dialog to the specified location, and allows the user to + * accept, or select a different file. + * @param outFile The output path + * @param inFileType The file type filter for the dialog. + * @return true If the user accepted the file, false if the user canceled. + */ +bool CDialogs::LocateFileReference(CUICFile &outFile, long inFileType) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + Q3DStudio::CString theFileFilter = CreateAllowedTypesString(inFileType, false); + + bool theResult = false; + + // Open the dialog. + CFileDialogEx theFileDialog(TRUE, nullptr, nullptr, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + theFileFilter, nullptr); + + // Set the initial directory to document path's directory (it should exist). + CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath()); + Q3DStudio::CFilePath theInitDir = + Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory(); + theFileDialog.SetInitialDirectory(theInitDir); + + // Set the title of the dialog + theFileDialog.SetWindowTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FILE)); + + INT_PTR refreshResult = theFileDialog.DoModal(); + + if (refreshResult == IDOK) { + Q3DStudio::CString thePath = theFileDialog.GetPathName(); + Q3DStudio::CString theName = theFileDialog.GetFileName(); + outFile = CUICFile(thePath, theName); + + // The user has accepted this file. + theResult = true; + } + + return theResult; +#endif + return false; +} + +//============================================================================== +/** + * Allows the user to select/confirm the folder to fix broken folder reference. + * This method opens a folder dialog to the specified location, and allows the user to + * accept, or select a different folder. + * @param outFile The output path + * @return true If the user accepted the file, false if the user canceled. + */ +bool CDialogs::LocateFolderReference(CUICFile &outFile) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + // Set the initial directory to document path's directory (it should exist). + CUICFile theDocumentFile(g_StudioApp.GetCore()->GetDoc()->GetDocumentPath()); + Q3DStudio::CFilePath theInitDir = + Q3DStudio::CFilePath(theDocumentFile.GetAbsolutePath()).GetDirectory(); + + // Set the title of the dialog + Q3DStudio::CString theDialogTitle(::LoadResourceString(IDS_PROJECT_CM_LOCATE_FOLDER)); + + return BrowseForFolderDialog(outFile, theInitDir, theDialogTitle); +#endif + return false; +} + +//============================================================================== +/** + * BrowseCallbackProc: Handles the callback proc for SHBrowseForFolder() + * + * Handles selecting the correct path when the SHBrowseForFolder dialog is + * initially displayed. + */ +#ifdef KDAB_TEMPORARILY_REMOVED +static int CALLBACK BrowseCallbackProc(HWND inHwnd, UINT inMsg, LPARAM /*inlParam*/, + LPARAM inlpData) +{ + switch (inMsg) { + case BFFM_INITIALIZED: + // Indicates the browse dialog box has finished initializing. The lParam value is zero. + if (inlpData != nullptr) { + // Do so by sendint the BFFM_SETSELECTION message to the inHwnd: + // Selects the specified folder. To use a PIDL to specify the folder, set the + // message's lParam to the PIDL, and set wParam to FALSE. To specify the folder's + // path, set the message's lParam value to point to a nullptr-terminated string with + // the path, and set wParam to TRUE. + + SendMessage(inHwnd, BFFM_SETSELECTION, (WPARAM)TRUE, (LPARAM)inlpData); + } + break; + + default: + break; + } + + return 0; +} +#endif + +//============================================================================== +/** + * Show browse for folder dialog + * @param outFile The output path + * @param inDefaultDir The default directory + * @param inDialogTitle The title of the dialog + * @return true If the user accepted the file, false if the user canceled. + */ +bool CDialogs::BrowseForFolderDialog(CUICFile &outFile, Q3DStudio::CString inDefaultDir, + Q3DStudio::CString inDialogTitle) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + bool theResult = false; + BROWSEINFO theInfo = { 0 }; + TCHAR theDispName[MAX_PATH] = { '\0' }; + + theInfo.pszDisplayName = theDispName; + theInfo.lpszTitle = inDialogTitle; + theInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS | BIF_NONEWFOLDERBUTTON; + theInfo.lpfn = BrowseCallbackProc; + theInfo.lParam = (LPARAM)inDefaultDir.c_str(); + + // Ask the user to choose a directory + LPITEMIDLIST theItem = SHBrowseForFolder(&theInfo); + + if (theItem != nullptr) { + TCHAR thePath[MAX_PATH] = { '\0' }; + // If a path was chosen + if (::SHGetPathFromIDList(theItem, thePath)) { + theResult = true; + outFile = CUICFile(Q3DStudio::CString(thePath)); + } + + // Free Memory used + LPMALLOC thePMalloc = 0; + if (SUCCEEDED(SHGetMalloc(&thePMalloc))) { + thePMalloc->Free(theItem); + thePMalloc->Release(); + } + } + + return theResult; +#endif + return false; +} + +//============================================================================== +/** + * Notify the user that the presentation we tried to load has failed. + * @param inPresentation The AKFile that we failed to load. + */ +void CDialogs::DisplayLoadingPresentationFailed(const CUICFile &inPresentation, + long inErrorIDS /*= -1 */) +{ + Q_UNUSED(inPresentation); + + if (inErrorIDS == -1) // if unspecified, default to the 'generic' string + inErrorIDS = IDS_ERROR_LOADPRESENTATION; + Q3DStudio::CString theErrorMessage; + theErrorMessage.Format(::LoadResourceString(inErrorIDS), + static_cast<const wchar_t *>(inPresentation.GetName())); + Q3DStudio::CString theErrorTitle(::LoadResourceString(IDS_ERROR_LOADPRESENTATION_TITLE)); + + if (m_ShowGUI) + CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false, + qApp->activeWindow()); + else { + std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl; + } +} + +//============================================================================== +/** + * Notify the user that the presentation we tried to save has failed. + * + * @param inSavedLocation The AKFile that we failed to save. + */ +void CDialogs::DisplaySavingPresentationFailed() +{ + Q3DStudio::CString theErrorMessage = ::LoadResourceString(IDS_ERROR_EXPORTPRESENTATION); + Q3DStudio::CString theErrorTitle = ::LoadResourceString(IDS_PROJNAME); + + if (m_ShowGUI) + CUICMessageBox::Show(theErrorTitle, theErrorMessage, CUICMessageBox::ICON_WARNING, false, + qApp->activeWindow()); + else { + std::cout << theErrorTitle.GetCharStar() << ": " << theErrorMessage.GetCharStar() << std::endl; + } +} + +//============================================================================== +/** + * Display a message box to indicate failure to overwrite a read-only file + * + * @param inSavedLocation + * the file location to be saved + * + * @return void + */ +void CDialogs::DisplaySaveReadOnlyFailed(const CUICFile &inSavedLocation) +{ + Q3DStudio::CString theMsg = ::LoadResourceString(IDS_SAVE_READONLY_WARNING); + Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME); + + Q3DStudio::CString theFormattedText; + theFormattedText.Format(theMsg, static_cast<const wchar_t *>(inSavedLocation.GetName())); + + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theFormattedText, CUICMessageBox::ICON_WARNING, false, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << theFormattedText.GetCharStar() << std::endl; + } +} + +//============================================================================== +/** + * Displays a CUICMessageBox using the specified parameters. The message box + * is modal to the main frame. This provides an easy way to place modal dialogs + * to the user, without requiring your class to know about the main frame or + * window refs. + * @param inTitle Title of the message box (not used on Mac) + * @param inText Text of the message + * @param inIcon Icon to be displayed next to the text + * @param inShowCancel true to show a Cancel button, false only show an OK button + * @return Indication of which button was pressed to dismiss the dialog + */ +CUICMessageBox::EMessageBoxReturn +CDialogs::DisplayMessageBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText, + CUICMessageBox::EMessageBoxIcon inIcon, bool inShowCancel) +{ + CUICMessageBox::EMessageBoxReturn theUserChoice; + + if (m_ShowGUI) { + theUserChoice = + CUICMessageBox::Show(inTitle, inText, inIcon, inShowCancel, qApp->activeWindow()); + } else { + std::cout << inTitle.GetCharStar() << ": " << inText.GetCharStar() << std::endl; + theUserChoice = CUICMessageBox::MSGBX_OK; + } + + return theUserChoice; +} + +int CDialogs::DisplayChoiceBox(const Q3DStudio::CString &inTitle, const Q3DStudio::CString &inText, + int inIcon) +{ + if (m_ShowGUI) { + QMessageBox box; + box.setWindowTitle(inTitle.toQString()); + box.setText(inText.toQString()); + switch (inIcon) { + case CUICMessageBox::ICON_WARNING: + box.setIcon(QMessageBox::Warning); + break; + case CUICMessageBox::ICON_ERROR: + box.setIcon(QMessageBox::Critical); + break; + case CUICMessageBox::ICON_INFO: + box.setIcon(QMessageBox::Information); + break; + default: + break; + } + box.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + switch (box.exec()) { + case QMessageBox::Yes: + return IDYES; + case QMessageBox::No: + return IDNO; + default: + Q_UNREACHABLE(); + } + } else { + std::cout << inTitle.GetCharStar() << ": " << inText << std::endl; + return IDYES; + } +} + +const char *CDialogs::GetDAEFileExtension() +{ + return "dae"; +} +const char *CDialogs::GetFbxFileExtension() +{ + return "fbx"; +} +// Null terminated list +const char **CDialogs::GetImgFileExtensions() +{ + return imgExts; +} +const char *CDialogs::GetImportFileExtension() +{ + return "import"; +} +const char *CDialogs::GetMeshFileExtension() +{ + return "mesh"; +} +const char *CDialogs::GetLUAFileExtension() +{ + return "lua"; +} +const char *CDialogs::GetQmlFileExtension() +{ + return "qml"; +} +const char **CDialogs::GetFontFileExtensions() +{ + return fontExts; +} +const char **CDialogs::GetEffectFileExtensions() +{ + return effectExts; +} +const char **CDialogs::GetMaterialFileExtensions() +{ + return materialExts; +} +const char **CDialogs::GetSoundFileExtensions() +{ + return soundExts; +} + +bool IsFileExtension(const char *inExt, const char **inExts) +{ + if (inExt == nullptr) + return false; + for (const char **ext = inExts; *ext != nullptr; ++ext) + if (QString::compare(inExt, *ext, Qt::CaseInsensitive) == 0) + return true; + return false; +} +bool CDialogs::IsImageFileExtension(const char *inExt) +{ + return IsFileExtension(inExt, imgExts); +} +bool CDialogs::IsFontFileExtension(const char *inExt) +{ + return IsFileExtension(inExt, fontExts); +} +bool CDialogs::IsEffectFileExtension(const char *inExt) +{ + return IsFileExtension(inExt, effectExts); +} +bool CDialogs::IsMaterialFileExtension(const char *inExt) +{ + return IsFileExtension(inExt, materialExts); +} +bool CDialogs::IsSoundFileExtension(const char *inExt) +{ + return IsFileExtension(inExt, soundExts); +} + +const wchar_t **CDialogs::GetWideImgFileExtensions() +{ + return wideImgExts; +} +const wchar_t *CDialogs::GetWideDAEFileExtension() +{ + return L"dae"; +} +const wchar_t *CDialogs::GetWideFbxFileExtension() +{ + return L"fbx"; +} +const wchar_t *CDialogs::GetWideImportFileExtension() +{ + return L"import"; +} +const wchar_t *CDialogs::GetWideMeshFileExtension() +{ + return L"mesh"; +} +const wchar_t *CDialogs::GetWideLUAFileExtension() +{ + return L"lua"; +} +const wchar_t **CDialogs::GetWideFontFileExtensions() +{ + return wideFontExts; +} +const wchar_t **CDialogs::GetWideEffectFileExtensions() +{ + return wideEffectExts; +} +const wchar_t **CDialogs::GetWideMaterialFileExtensions() +{ + return wideMaterialExts; +} + +bool IsFileExtension(const wchar_t *inExt, const wchar_t **inExts) +{ + if (inExt == nullptr) + return false; + for (const wchar_t **ext = inExts; *ext != nullptr; ++ext) { + if (QString::compare(QString::fromWCharArray(inExt), + QString::fromWCharArray(*ext), Qt::CaseInsensitive) == 0) { + return true; + } + } + return false; +} +bool CDialogs::IsImageFileExtension(const wchar_t *inExt) +{ + return IsFileExtension(inExt, wideImgExts); +} +bool CDialogs::IsFontFileExtension(const wchar_t *inExt) +{ + return IsFileExtension(inExt, wideFontExts); +} +bool CDialogs::IsEffectFileExtension(const wchar_t *inExt) +{ + return IsFileExtension(inExt, wideEffectExts); +} + +bool CDialogs::IsMaterialFileExtension(const wchar_t *inExt) +{ + return IsFileExtension(inExt, wideMaterialExts); +} + +bool CDialogs::IsPathFileExtension(const wchar_t *inExt) +{ + return QString::compare(QString::fromWCharArray(inExt), "svg", Qt::CaseInsensitive) == 0; +} + +bool CDialogs::IsPathBufferExtension(const wchar_t *inExt) +{ + return QString::compare(QString::fromWCharArray(inExt), "path", Qt::CaseInsensitive) == 0; +} + +bool CDialogs::IsSoundFileExtension(const wchar_t *inExt) +{ + return IsFileExtension(inExt, wideSoundExts); +} + +//============================================================================== +/** + * File picker. + * Format for filter is as follows: + * Each entry in the filter list is '<description>|*.ext' + * String must end with '|' + * Example, XML Exporter (*.xml)|*.xml|All files (*.*)|*.*| + * + * @param inFileExtensionFilter Well-formed extension filter string. See comments + *above for the format. + * @param inDefault Default string in case of abortion or + *failure + * @return chosen file path if successful, inDefault otherwise. + */ +Q3DStudio::CString CDialogs::GetFilePathChoice(const Q3DStudio::CString &inFileExtensionFilter, + const Q3DStudio::CString &inDefault, + const Q3DStudio::CString *inDialogTitle /*= nullptr */) +{ + Q3DStudio::CString theResult(inDefault); + +#ifdef KDAB_TEMPORARILY_REMOVED + CFileDialogEx theFileDlg(true, nullptr, nullptr, 0, inFileExtensionFilter, AfxGetMainWnd()); + + Q3DStudio::CString theInitDir = + CPreferences::GetUserPreferences().GetStringValue("LastChosenFile", ""); + theFileDlg.SetInitialDirectory(theInitDir); + + // Remember the filter setting between invokations + static long s_LastFilterIndex = -1; + if (s_LastFilterIndex > 0) + theFileDlg.SetFilterIndex(s_LastFilterIndex); + + if (inDialogTitle) // Set the title of the dialog if specied + theFileDlg.SetWindowTitle(*inDialogTitle); + + if (theFileDlg.DoModal() == IDOK) { + theResult = theFileDlg.GetPathName(); + CPreferences::GetUserPreferences().SetStringValue("LastChosenFile", theResult); + s_LastFilterIndex = theFileDlg.GetLastFilterIndex(); + } +#endif + + return theResult; +} + +//============================================================================== +/** + * CreateAllowedTypesString: Creates the string used to determine allowable types for import or + *for filereferences + * @return the string that dynamicly created with the extensions supported. + */ +QString CDialogs::CreateAllowedTypesString(long inFileTypeFilter, bool inForImport) +{ + QString theReturnString; + size_t theCount = inForImport ? g_NumAllowedImportTypes : g_NumAllowedFileReferencesTypes; + for (size_t idx = 0; idx < theCount; ++idx) { + const SAllowedTypesEntry &entry = + inForImport ? g_AllowedImportTypes[idx] : g_AllowedFileReferencesTypes[idx]; + if (inFileTypeFilter == Q3DStudio::DocumentEditorFileType::Unknown + || inFileTypeFilter == entry.m_FileType) { + QString theTypeString(::LoadResourceString(entry.m_ResourceStringId).toQString()); + QString theExtensions(CreateExtensionsList(entry.m_FileExtensions).toQString()); + theReturnString += theTypeString + " (" + theExtensions + ");;"; + } + } + return theReturnString; +} + +//============================================================================== +/** + * Display a error dialog box with the given text string that describes the error. + */ +void CDialogs::DisplayKnownErrorDialog(const Q3DStudio::CString &inErrorText) +{ + if (inErrorText.Length() > 0) // make sure this is valid + { + Q3DStudio::CString theTitle(::LoadResourceString(IDS_PROJNAME)); + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, inErrorText, CUICMessageBox::ICON_ERROR, false, + qApp->activeWindow()); + else + std::cout << inErrorText.GetCharStar() << ": " << inErrorText.GetCharStar() << std::endl; + } +} + +//============================================================================== +/** + * Prompt the user to save the document before losing their changes. + * This is used when closing, loading or newing up a document when the current + * one has modifications. + * @return the user's choice. + */ +CDialogs::ESavePromptResult CDialogs::PromptForSave() +{ + Q3DStudio::CString theDocTitle; + + CUICFile theCurrentDoc = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath(); + if (theCurrentDoc.IsFile()) + theDocTitle = theCurrentDoc.GetName(); + else // if the current doc has not been saved then use the default title. + theDocTitle = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE); + + Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_SAVE); + thePrompt.Format(thePrompt, static_cast<const wchar_t *>(theDocTitle)); + + int theChoice = QMessageBox::warning(nullptr, ::LoadResourceString(IDS_PROJNAME).toQString(), + thePrompt.toQString(), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel); + + ESavePromptResult theResult = CANCEL_OPERATION; + + switch (theChoice) { + case QMessageBox::Yes: + theResult = SAVE_FIRST; + break; + case QMessageBox::No: + theResult = CONTINUE_NO_SAVE; + break; + case QMessageBox::Cancel: + theResult = CANCEL_OPERATION; + break; + default: + break; + } + + return theResult; +} + +//============================================================================== +/** + * Prompt the user for a file to save to from the SaveAs menu option. + * @return an invalid file if the user cancels the save dialog. + */ +std::pair<CUICFile, bool> CDialogs::GetSaveAsChoice(const Q3DStudio::CString &inDialogTitle, + bool inFilenameUntitled) +{ + CUICFile theFile(""); + Q3DStudio::CString theFileExt; + Q3DStudio::CString theImportFilter; + + Q3DStudio::CString theFilename = g_StudioApp.GetCore()->GetDoc()->GetDocumentPath().GetAbsolutePath(); + + if (theFilename == "" || inFilenameUntitled) + theFilename = ::LoadResourceString(IDS_UNTITLED_DOCUMENT_TITLE); + + theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP); + theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP); + + theImportFilter += " (*" + theFileExt + ")|*" + theFileExt + "|"; + + QFileDialog theFileDlg; + theFileDlg.setOption(QFileDialog::DontConfirmOverwrite); + const QFileInfo fi(m_LastSaveFile.toQString()); + theFileDlg.setDirectory((fi.path() == QLatin1Char('.')) ? QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) : fi.path()); + theFileDlg.setAcceptMode(QFileDialog::AcceptSave); + theFileDlg.setDefaultSuffix(theFileExt.toQString()); + if (inDialogTitle != "") + theFileDlg.setWindowTitle(inDialogTitle.toQString()); + + bool theCreateDir = false; + bool theShowDialog = true; + + while (theShowDialog && theFileDlg.exec()) { + theShowDialog = false; + theFile = CUICFile(Q3DStudio::CString::fromQString(theFileDlg.selectedFiles().front())); + + m_LastSaveFile = theFile.GetAbsolutePath(); + // customising a dialog box will force us to use non-native. + // defaulting this for now, until we can agree a better workflow for + // creating new projects + theCreateDir = true; + + if (theCreateDir) { + // If user checks "Create directory for project" + // we need to check manually if the file in the directory already exists (because the + // default file dialog can't do that for you) + // If the file exists, show warning message if user wants to overwrite the file + // This is to fix bug #6315: Create new project in folder with same name will overwrite + // existing file without warning + Q3DStudio::CFilePath theFinalDir; + Q3DStudio::CFilePath theFinalDoc; + g_StudioApp.GetCore()->GetCreateDirectoryFileName(theFile, theFinalDir, theFinalDoc); + + // Update last save file to final doc + m_LastSaveFile = theFinalDoc; + if (theFinalDoc.Exists()) { + const QString theTitle(QObject::tr("Confirm Save As")); + const QString filePath(theFinalDir.GetFileName().toQString() + QDir::separator() + theFinalDoc.GetFileName().toQString()); + const QString theString = QObject::tr("%1 already exists.\nDo you want to replace it?").arg(filePath); + + auto result = QMessageBox::question(nullptr, theTitle, theString); + if (result != QMessageBox::Yes) { + // Reset the file and show the file dialog again + theFile = CUICFile(""); + theShowDialog = true; + continue; + } + } // of over-writing case + } + } + + return std::make_pair(theFile, theCreateDir); +} + +//============================================================================== +/** + * Prompt the user for a file to create. + * @return an invalid file if the user cancels the save dialog. + */ +std::pair<CUICFile, bool> +CDialogs::GetNewDocumentChoice(const Q3DStudio::CString &inInitialDirectory) +{ + if (inInitialDirectory.size()) + m_LastSaveFile = inInitialDirectory; + return GetSaveAsChoice(::LoadResourceString(IDS_CREATE_NEW_DOCUMENT_TITLE), true); +} + +//============================================================================== +/** + * Prompt the user for a file to open. + * This will return an invalid file if the user cancels the save dialog. + */ +CUICFile CDialogs::GetFileOpenChoice(const Q3DStudio::CString &inInitialDirectory) +{ + CUICFile theFile(""); + Q3DStudio::CString theFileExt; + Q3DStudio::CString theImportFilter; + + theFileExt = ::LoadResourceString(IDS_FILE_EXT_UIP); + theImportFilter = ::LoadResourceString(IDS_FILE_DESC_UIP); + + theImportFilter += " (*" + theFileExt + ")"; + + QFileDialog theFileDlg(qApp->activeWindow(), QString(), inInitialDirectory.toQString(), theImportFilter.toQString()); + theFileDlg.setAcceptMode(QFileDialog::AcceptOpen); + + if (theFileDlg.exec() == QDialog::Accepted) { + QFileInfo fi(theFileDlg.selectedFiles().first()); + Q3DStudio::CString thePath = Q3DStudio::CString::fromQString(fi.absolutePath()); + Q3DStudio::CString theName = Q3DStudio::CString::fromQString(fi.fileName()); + theFile = CUICFile(thePath, theName); + + m_LastSaveFile = theFile.GetAbsolutePath(); + } + + return theFile; +} + +//============================================================================== +/** + * Prompt the user to make sure they want to revert the current project. + * @return true if they do want to continue with the revert. + */ +bool CDialogs::ConfirmRevert() +{ + bool theConfirmation = false; + Q3DStudio::CString thePrompt = ::LoadResourceString(IDS_PROMPT_FOR_REVERT); + Q3DStudio::CString theTitle = ::LoadResourceString(IDS_PROJNAME); + + CUICMessageBox::EMessageBoxReturn theChoice; + + if (m_ShowGUI) + theChoice = CUICMessageBox::Show(theTitle, thePrompt, CUICMessageBox::ICON_WARNING, true, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << thePrompt.GetCharStar() << std::endl; + theChoice = CUICMessageBox::MSGBX_OK; + } + + // user decided to go ahead and delete all unused resources + if (theChoice == CUICMessageBox::MSGBX_OK) + theConfirmation = true; + + return theConfirmation; +} + +//============================================================================== +/** + * Displays a progress screen, if there is not one aleady being shown. The + * progress screen doesn't get dismissed until you call + * CDialogs::DestroyProgressScreen(). + * @param inActionText text to be displayed above the file name on the screen + * @param inFileName name of the file that you are loading + * @param inWindowTitle the window's title + */ +void CDialogs::DisplayProgressScreen(const Q3DStudio::CString &inActionText, + const Q3DStudio::CString &inFileName, + const Q3DStudio::CString &inWindowTitle) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + if (m_ShowGUI && (!m_ProgressPalette || !m_ProgressPalette->GetSafeHwnd())) { + m_ProgressPalette = new CProgressPalette(); + CViews::CreateDialogAndView(RUNTIME_CLASS(CProgressView), m_ProgressPalette, + (CFrameWnd *)AfxGetMainWnd(), inWindowTitle); + m_ProgressPalette->ShowDialog(); + m_ProgressPalette->InitialUpdate(); + m_ProgressPalette->SetActionText(inActionText); + m_ProgressPalette->SetFileName(inFileName); + m_ProgressPalette->RedrawWindow(nullptr, nullptr, RDW_UPDATENOW); + } +#endif +} + +//============================================================================== +/** + * Retrieve the pointer to the progress screen. + * @return m_ProgressPalette + */ +IProgressCallback *CDialogs::GetProgressScreen() const +{ +#ifdef KDAB_TEMPORARILY_REMOVED + return m_ProgressPalette; +#endif + return nullptr; +} + +//============================================================================== +/** + * If a loading screen is currently being shown, this function destroys it. You + * can show the loading screen again with another call to + * CDialogs::DisplayLoadingScreen(). + */ +void CDialogs::DestroyProgressScreen() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + if (m_ShowGUI && (m_ProgressPalette && m_ProgressPalette->GetSafeHwnd())) { + // Don't call delete on m_ProgressPalette. You should only call DestroyWindow on + // CFrameWnds. See the MSDN. + m_ProgressPalette->DestroyWindow(); + m_ProgressPalette = nullptr; + } +#endif +} + +//============================================================================== +/** + * Prompt the user for the Object Timebar color. + * @param ioColor + * @return true if we successfully obtained a color using the displayed dialog. + */ +bool CDialogs::PromptObjectTimebarColor(CColor &ioColor) +{ +#ifdef KDAB_TEMPORARILY_REMOVED + std::auto_ptr<CColorDialog> theColorDlg(new CColorDialog(ioColor, CC_SOLIDCOLOR | CC_FULLOPEN)); + ::CColor theSelectedColor; + if (theColorDlg->DoModal() == IDOK) { + ioColor = theColorDlg->GetColor(); + return true; + } + return false; +#endif + return false; +} + +//============================================================================== +/** + * Display statistics from profiling. + */ +void CDialogs::DisplayProfilingStatistics() +{ + Q3DStudio::CString theStatistics = "<Not Enabled>"; +#ifdef KDAB_TEMPORARILY_REMOVED +#ifdef PERFORM_PROFILE + CMasterProf *theMasterP = CMasterProf::GetInstance(); + + for (long theIndex = 0; theIndex < theMasterP->GetProfilerCount(); ++theIndex) { + CMethProf *theProf = theMasterP->GetProfiler(theIndex); + if (theProf->GetCount() > 0) { + theStatistics += theProf->GetDescription(); + theStatistics += "\n"; + } + } +#endif // #ifdef PERFORM_PROFILE + if (m_ShowGUI) + CUICMessageBox::Show("Profiling Statistics", theStatistics, CUICMessageBox::ICON_INFO); + else { + std::cout << "Profiling Statistics" + << ": " << theStatistics.GetMulti() << std::endl; + } +#endif +} + +//============================================================================== +/** + * Inform the user that the environment variables entered does not match the format + * expected, listing down all those settings that are wrong. + * @param inErrorMessage the listing of all those errors. + */ +void CDialogs::DisplayEnvironmentVariablesError(const Q3DStudio::CString &inErrorMessage) +{ + Q3DStudio::CString theTitle = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_TITLE); + Q3DStudio::CString theMessage = ::LoadResourceString(IDS_ERROR_PROJECT_VARIABLES_MSG); + theMessage += inErrorMessage; + theMessage += ::LoadResourceString(IDS_PROJECT_VARIABLES_FORMAT); + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false, + qApp->activeWindow()); + else { + std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl; + } +} + +//============================================================================== +/** + * Reset settings. + * Typically inCurrentDocPath is only set when Studio is first launched. + * @param inCurrentDocPath the current document path, if any. Application directory if + *there is none. + */ +void CDialogs::ResetSettings(const Q3DStudio::CString &inCurrentDocPath) +{ + // Initialize the default dir/paths to the current document path if specified, otherwise leave + // everything as it is. + if (!inCurrentDocPath.IsEmpty()) { + m_LastSaveFile = inCurrentDocPath; + } +} + +bool CDialogs::DisplayResetKeyframeValuesDlg() +{ +#ifdef KDAB_TEMPORARILY_REMOVED + CResetKeyframeValuesDlg theDialog; + return theDialog.DoModal() == IDOK; +#endif + return false; +} + +//============================================================================== +/** + * User trying to do a pathological paste, such as pasting a component copied from a different + *instance + * of Studio into an instance of the same component that already exists in the current instance + *of Studio, and + * is potentially replaced and deleted. + */ +void CDialogs::DisplayPasteFailed() +{ + Q3DStudio::CString theTitle(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_TITLE)); + Q3DStudio::CString theMessage(::LoadResourceString(IDS_ERROR_PATHOLOGICAL_PASTE_MESSAGE)); + + if (m_ShowGUI) + CUICMessageBox::Show(theTitle, theMessage, CUICMessageBox::ICON_ERROR, false, + qApp->activeWindow()); + else + std::cout << theTitle.GetCharStar() << ": " << theMessage.GetCharStar() << std::endl; +} + +//============================================================================== +/** + * Video card OpenGL version is too low to be supported. + */ +void CDialogs::DisplayGLVersionError(const Q3DStudio::CString &inGLVersion, + const Q3DStudio::CString &inMinVersion) +{ + DisplayGLVersionDialog(inGLVersion, inMinVersion, true); +} + +//============================================================================== +/** + * Video card OpenGL version is outdated, but could be usable. + */ +void CDialogs::DisplayGLVersionWarning(const Q3DStudio::CString &inGLVersion, + const Q3DStudio::CString &inRecommendedVersion) +{ + DisplayGLVersionDialog(inGLVersion, inRecommendedVersion, false); +} + +//============================================================================== +/** + * Display the error dialog or warning dialog that OpenGL version is lower than what is + *expected + */ +void CDialogs::DisplayGLVersionDialog(const Q3DStudio::CString &inGLVersion, + const Q3DStudio::CString &inRecommendedVersion, bool inError) +{ + long theTitleResourceID; + long theMessageResourceID; + + if (inError) { + theTitleResourceID = IDS_ERROR_MSGTITLE; + theMessageResourceID = IDS_GL_VERSION_ERROR; + } else { + theTitleResourceID = IDS_WARNING_MSGTITLE; + theMessageResourceID = IDS_GL_VERSION_WARNING; + } + +#ifdef KDAB_TEMPORARILY_REMOVED + Q3DStudio::CString theTitle(::LoadResourceString(theTitleResourceID)); + Q3DStudio::CString theMessage(::LoadResourceString(theMessageResourceID)); + Q3DStudio::CString theFormattedMessage; + theFormattedMessage.Format(theMessage, static_cast<const wchar_t *>(inGLVersion), + static_cast<const wchar_t *>(inRecommendedVersion)); + + CGLVersionDlg theGLVersionDlg; + theGLVersionDlg.Initialize(theTitle, theFormattedMessage, inError); + theGLVersionDlg.DoModal(); + + if (theGLVersionDlg.GetDontShowAgain()) + CStudioPreferences::SetDontShowGLVersionDialog(true); +#endif +} diff --git a/src/Authoring/Studio/_Win/Workspace/Views.cpp b/src/Authoring/Studio/_Win/Workspace/Views.cpp new file mode 100644 index 00000000..50ab6f62 --- /dev/null +++ b/src/Authoring/Studio/_Win/Workspace/Views.cpp @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2002 NVIDIA Corporation. +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt 3D Studio. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//============================================================================== +// Prefix +//============================================================================== +#include "stdafx.h" +#include "Views.h" + +//============================================================================== +// Includes +//============================================================================== +#ifdef KDAB_TEMPORARILY_REMOVED +#include "Doc.h" +#endif +#include "MainFrm.h" +#ifdef KDAB_TEMPORARILY_REMOVED +#include "TimelineTimelineLayout.h" +#include "ScalableScroller.h" +#include "PaletteManager.h" +#include "HotKeys.h" +#include "Dispatch.h" +#include "ActionControl.h" +#include "StudioPaletteBar.h" +#endif + +//============================================================================== +// Implementation +//============================================================================== + +//============================================================================= +/** + * Constructor + */ +CViews::CViews(CStudioApp * /*inStudioApp*/) + : m_MainFrame(nullptr) +{ +} + +//============================================================================= +/** + * Destructor + */ +CViews::~CViews() +{ + DestroyViews(); +} + +//============================================================================= +/** + * + */ +void CViews::CreateViews() +{ + // To create the main window, this code creates a new frame window + // object and then sets it as the application's main window object + m_MainFrame = new CMainFrame(); + m_MainFrame->show(); +#ifdef KDAB_TEMPORARILY_REMOVED + // create and load the frame with its resources + m_MainFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, nullptr, nullptr); + + m_MainFrame->RestoreLayout(); +#endif +} + +//============================================================================= +/** + * + */ +void CViews::DestroyViews() +{ + if (m_MainFrame) { + // Do NOT use delete to destroy a CFrameWnd object! Use DestroyWindow() instead. + m_MainFrame->deleteLater(); + m_MainFrame = nullptr; + } +} + +//============================================================================== +// Keyboard +//============================================================================== + +//============================================================================= +/** + * Register all Application specific shortcut keys. + * Used to map hotkeys that are active through the whole app, not just one + * view. + * @param inHotKeys the handler to register on. + */ +void CViews::RegisterGlobalKeyboardShortcuts(CHotKeys *inHotKeys) +{ + if (m_MainFrame) + m_MainFrame->RegisterGlobalKeyboardShortcuts(inHotKeys); +} + +//============================================================================= +/** + * NO ONE SHOULD USE THIS FUNCTION OTHER THAN THE MAINFRAME ON WINDOWS + */ +CMainFrame *CViews::GetMainFrame() +{ + return m_MainFrame; +} + +//============================================================================= +/** + * + */ +void CViews::RecheckMainframeSizingMode() +{ + if (m_MainFrame != nullptr) + m_MainFrame->RecheckSizingMode(); +} + +//============================================================================== +// Static +//============================================================================== + +//============================================================================= +/** + * Creates a palette and the associated view. + * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that + * inherits from MFC::CView (must implement dynamic creation) and is the view + * that you want associated with the palette. + * @param inPalette Palette that you want the view attached to + * @param inParent Parent window or nullptr for top level windows + * @param inWindowTitle Title caption to appear on the title bar of the palette + * @param inShowWindow true to show the window after creation, false to hide it + */ +#ifdef KDAB_TEMPORARILY_REMOVED +void CViews::CreatePaletteAndView(CRuntimeClass *inClass, CStudioPaletteBar *inPalette, + CFrameWnd *inParent, Q3DStudio::CString inWindowTitle) +{ + CCreateContext theCreateContext; + memset(&theCreateContext, 0, sizeof(CCreateContext)); + theCreateContext.m_pNewViewClass = inClass; + theCreateContext.m_pCurrentFrame = inParent; + theCreateContext.m_pCurrentDoc = nullptr; + + inPalette->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext, + CPaletteManager::GetUniquePaletteId(), inParent); +} +#endif + +//============================================================================= +/** + * Creates a dialog and the associated view. + * @param inClass Should be RUNTIME_CLASS( CCLASS ) where CCLASS is a class that + * inherits from MFC::CView (must implement dynamic creation) and is the view + * that you want associated with the palette. + * @param inPalette Palette that you want the view attached to + * @param inParent Parent window or nullptr for top level windows + * @param inWindowTitle Title caption to appear on the title bar of the palette + * @param inShowWindow true to show the window after creation, false to hide it + */ +#ifdef KDAB_TEMPORARILY_REMOVED +void CViews::CreateDialogAndView(CRuntimeClass *inClass, CStudioDialog *inDialog, + CFrameWnd *inParent, Q3DStudio::CString inWindowTitle) +{ + CCreateContext theCreateContext; + memset(&theCreateContext, 0, sizeof(CCreateContext)); + theCreateContext.m_pNewViewClass = inClass; + theCreateContext.m_pCurrentFrame = inParent; + theCreateContext.m_pCurrentDoc = nullptr; + + inDialog->Create(::CString(inWindowTitle.GetMulti()), &theCreateContext, inParent); +} +#endif |