Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
@@ -0,0 +1,636 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <precompiled.h>
#include <qtoolbutton.h>
#include <qscopedvaluerollback.h>
#include <QFocusEvent>
#include <QHeaderView>
#include <QWidgetAction>
#include <GraphCanvas/Components/StyleBus.h>
#include <GraphCanvas/Widgets/StyledItemDelegates/IconDecoratedNameDelegate.h>
#include <Editor/View/Dialogs/ContainerWizard/ContainerTypeLineEdit.h>
#include <Editor/View/Dialogs/ContainerWizard/ui_ContainerTypeLineEdit.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
namespace ScriptCanvasEditor
{
//////////////////////
// ContainerTypeMenu
//////////////////////
ContainerTypeMenu::ContainerTypeMenu(QWidget* parent)
: QDialog(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
, m_disableHiding(false)
, m_ignoreNextFocusIn(false)
{
setProperty("HasNoWindowDecorations", true);
setAttribute(Qt::WA_ShowWithoutActivating);
m_proxyModel.setSourceModel(GetModel());
m_proxyModel.sort(DataTypePaletteModel::ColumnIndex::Type);
m_tableView.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_tableView.setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableView.setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_tableView.setItemDelegateForColumn(DataTypePaletteModel::Type, aznew GraphCanvas::IconDecoratedNameDelegate(this));
m_tableView.setModel(GetProxyModel());
m_tableView.verticalHeader()->hide();
m_tableView.horizontalHeader()->hide();
m_tableView.horizontalHeader()->setSectionResizeMode(DataTypePaletteModel::ColumnIndex::Pinned, QHeaderView::ResizeMode::ResizeToContents);
m_tableView.horizontalHeader()->setSectionResizeMode(DataTypePaletteModel::ColumnIndex::Type, QHeaderView::ResizeMode::Stretch);
m_tableView.installEventFilter(this);
m_tableView.setFocusPolicy(Qt::FocusPolicy::ClickFocus);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(&m_tableView);
setLayout(layout);
m_disableHidingStateSetter.AddStateController(GetStateController());
QObject::connect(&m_tableView, &QTableView::clicked, this, &ContainerTypeMenu::OnTableClicked);
}
ContainerTypeMenu::~ContainerTypeMenu()
{
}
DataTypePaletteModel* ContainerTypeMenu::GetModel()
{
return &m_model;
}
const DataTypePaletteModel* ContainerTypeMenu::GetModel() const
{
return &m_model;
}
DataTypePaletteSortFilterProxyModel* ContainerTypeMenu::GetProxyModel()
{
return &m_proxyModel;
}
const DataTypePaletteSortFilterProxyModel* ContainerTypeMenu::GetProxyModel() const
{
return &m_proxyModel;
}
void ContainerTypeMenu::ShowMenu()
{
clearFocus();
m_tableView.clearFocus();
show();
m_disableHidingStateSetter.ReleaseState();
}
void ContainerTypeMenu::HideMenu()
{
m_disableHidingStateSetter.ReleaseState();
m_tableView.clearFocus();
clearFocus();
reject();
}
void ContainerTypeMenu::reject()
{
if (!m_disableHiding.GetState())
{
QDialog::reject();
}
}
bool ContainerTypeMenu::eventFilter(QObject* object, QEvent* event)
{
if (object == &m_tableView)
{
if (event->type() == QEvent::FocusOut)
{
HandleFocusOut();
}
else if (event->type() == QEvent::FocusIn)
{
HandleFocusIn();
}
}
return false;
}
void ContainerTypeMenu::focusInEvent(QFocusEvent* focusEvent)
{
QDialog::focusInEvent(focusEvent);
if (focusEvent->isAccepted())
{
if (!m_ignoreNextFocusIn)
{
HandleFocusIn();
}
else
{
m_ignoreNextFocusIn = false;
}
}
}
void ContainerTypeMenu::focusOutEvent(QFocusEvent* focusEvent)
{
QDialog::focusOutEvent(focusEvent);
HandleFocusOut();
}
void ContainerTypeMenu::showEvent(QShowEvent* showEvent)
{
QDialog::showEvent(showEvent);
// So, despite me telling it to not activate, the window still gets a focus in event.
// But, it doesn't get a foccus out event, since it doesn't actually accept the focus in event?
m_ignoreNextFocusIn = true;
m_tableView.selectionModel()->clearSelection();
Q_EMIT VisibilityChanged(true);
}
void ContainerTypeMenu::hideEvent(QHideEvent* hideEvent)
{
QDialog::hideEvent(hideEvent);
clearFocus();
Q_EMIT VisibilityChanged(false);
m_tableView.selectionModel()->clearSelection();
}
GraphCanvas::StateController<bool>* ContainerTypeMenu::GetStateController()
{
return &m_disableHiding;
}
void ContainerTypeMenu::SetSelectedRow(int row)
{
m_tableView.selectionModel()->clear();
if (row <= m_proxyModel.rowCount()
&& row >= 0)
{
QItemSelection rowSelection(m_proxyModel.index(row, 0), m_proxyModel.index(row, m_proxyModel.columnCount()-1));
m_tableView.selectionModel()->select(rowSelection, QItemSelectionModel::Select);
m_tableView.scrollTo(m_proxyModel.index(row, 0));
}
}
int ContainerTypeMenu::GetSelectedRow() const
{
if (m_tableView.selectionModel()->hasSelection())
{
QModelIndexList selectedIndexes = m_tableView.selectionModel()->selectedIndexes();
if (!selectedIndexes.empty())
{
return selectedIndexes.front().row();
}
}
return -1;
}
AZ::TypeId ContainerTypeMenu::GetSelectedTypeId() const
{
QModelIndexList selectedIndexes = m_tableView.selectionModel()->selectedIndexes();
if (!selectedIndexes.empty())
{
QModelIndex firstSelection = selectedIndexes.front();
QModelIndex sourceIndex = m_proxyModel.mapToSource(firstSelection);
return m_model.FindTypeIdForIndex(sourceIndex);
}
return AZ::TypeId::CreateNull();
}
void ContainerTypeMenu::OnTableClicked(const QModelIndex& modelIndex)
{
if (modelIndex.isValid())
{
QModelIndex sourceIndex = m_proxyModel.mapToSource(modelIndex);
AZ::TypeId typeId = m_model.FindTypeIdForIndex(sourceIndex);
if (!typeId.IsNull())
{
Q_EMIT ContainerTypeSelected(typeId);
QTimer::singleShot(0, [this]() { accept(); });
}
}
}
void ContainerTypeMenu::HandleFocusIn()
{
m_disableHidingStateSetter.SetState(true);
}
void ContainerTypeMenu::HandleFocusOut()
{
m_disableHidingStateSetter.ReleaseState();
QTimer::singleShot(0, [this]() { reject(); });
}
//////////////////////////
// ContainerTypeLineEdit
//////////////////////////
ContainerTypeLineEdit::ContainerTypeLineEdit(int index, QWidget* parent)
: QWidget(parent)
, m_ui(new Ui::ContainerTypeLineEdit())
, m_ignoreNextComplete(false)
, m_recursionBlocker(false)
, m_index(index)
, m_lastId(azrtti_typeid<void>())
, m_dataTypeMenu(parent)
{
m_ui->setupUi(this);
QAction* action = m_ui->variableType->addAction(QIcon(":/ScriptCanvasEditorResources/Resources/triangle.png"), QLineEdit::ActionPosition::TrailingPosition);
QObject::connect(action, &QAction::triggered, this, &ContainerTypeLineEdit::OnOptionsClicked);
m_completer.setModel(m_dataTypeMenu.GetModel());
m_completer.setCompletionColumn(DataTypePaletteModel::ColumnIndex::Type);
m_completer.setCompletionMode(QCompleter::CompletionMode::InlineCompletion);
m_completer.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
m_ui->variableType->installEventFilter(this);
m_ui->variableType->setCompleter(&m_completer);
QObject::connect(m_ui->variableType, &QLineEdit::textEdited, this, &ContainerTypeLineEdit::OnTextChanged);
QObject::connect(m_ui->variableType, &QLineEdit::returnPressed, this, &ContainerTypeLineEdit::OnReturnPressed);
QObject::connect(m_ui->variableType, &QLineEdit::editingFinished, this, &ContainerTypeLineEdit::OnEditComplete);
m_filterTimer.setInterval(500);
QObject::connect(&m_filterTimer, &QTimer::timeout, this, &ContainerTypeLineEdit::UpdateFilter);
QObject::connect(&m_dataTypeMenu, &ContainerTypeMenu::ContainerTypeSelected, this, &ContainerTypeLineEdit::SelectType);
QObject::connect(&m_dataTypeMenu, &ContainerTypeMenu::VisibilityChanged, this, &ContainerTypeLineEdit::DataTypeMenuVisibilityChanged);
m_dataTypeMenu.accept();
m_disableHidingStateSetter.AddStateController(m_dataTypeMenu.GetStateController());
}
ContainerTypeLineEdit::~ContainerTypeLineEdit()
{
m_dataTypeMenu.accept();
}
void ContainerTypeLineEdit::SetDisplayName(AZStd::string_view name)
{
m_ui->nameDisplay->setText(name.data());
}
void ContainerTypeLineEdit::SetDataTypes(const AZStd::unordered_set< AZ::TypeId >& dataTypes)
{
m_dataTypeMenu.GetModel()->ClearTypes();
m_dataTypeMenu.GetModel()->PopulateVariablePalette(dataTypes);
}
AZ::TypeId ContainerTypeLineEdit::GetDefaultTypeId() const
{
const DataTypePaletteSortFilterProxyModel* proxyModel = m_dataTypeMenu.GetProxyModel();
if (proxyModel->rowCount() > 0)
{
QModelIndex index = proxyModel->index(0, 0);
QModelIndex sourceIndex = proxyModel->mapToSource(index);
const DataTypePaletteModel* paletteModel = m_dataTypeMenu.GetModel();
return paletteModel->FindTypeIdForIndex(sourceIndex);
}
return azrtti_typeid<void>();
}
void ContainerTypeLineEdit::SelectType(const AZ::TypeId& typeId)
{
if (DisplayType(typeId))
{
Q_EMIT TypeChanged(m_index, typeId);
}
}
bool ContainerTypeLineEdit::DisplayType(const AZ::TypeId& typeId)
{
QSignalBlocker signalBlocker(m_ui->variableType);
AZStd::string typeName = m_dataTypeMenu.GetModel()->FindTypeNameForTypeId(typeId);
if (!typeName.empty())
{
m_completer.setCompletionPrefix(typeName.c_str());
m_ui->variableType->setText(typeName.c_str());
m_lastId = typeId;
}
else
{
m_completer.setCompletionPrefix("");
m_ui->variableType->setText("");
m_lastId = azrtti_typeid<void>();
}
// Clear out any selection since this might be coming from an auto complete
m_ui->variableType->setSelection(0, 0);
const QPixmap* pixmapIcon = nullptr;
GraphCanvas::StyleManagerRequestBus::EventResult(pixmapIcon, ScriptCanvasEditor::AssetEditorId, &GraphCanvas::StyleManagerRequests::GetDataTypeIcon, m_lastId);
m_ui->iconLabel->setPixmap((*pixmapIcon));
return !typeName.empty();
}
QWidget* ContainerTypeLineEdit::GetLineEdit() const
{
return m_ui->variableType;
}
void ContainerTypeLineEdit::ResetLineEdit()
{
m_disableHidingStateSetter.ReleaseState();
m_lastId = azrtti_typeid<void>();
m_completer.setCompletionPrefix("");
m_dataTypeMenu.GetProxyModel()->SetFilter("");
HideDataTypeMenu();
}
void ContainerTypeLineEdit::CancelDataInput()
{
DisplayType(m_lastId);
HideDataTypeMenu();
}
void ContainerTypeLineEdit::HideDataTypeMenu()
{
m_dataTypeMenu.HideMenu();
}
bool ContainerTypeLineEdit::eventFilter(QObject* obj, QEvent* event)
{
if (obj == m_ui->variableType)
{
switch (event->type())
{
case QEvent::FocusOut:
{
m_disableHidingStateSetter.ReleaseState();
QTimer::singleShot(0, [this]() { this->m_dataTypeMenu.reject(); });
break;
}
case QEvent::KeyPress:
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Down)
{
if (m_dataTypeMenu.isHidden())
{
m_dataTypeMenu.GetProxyModel()->SetFilter("");
DisplayMenu();
}
int selectedIndex = m_dataTypeMenu.GetSelectedRow();
if (selectedIndex < 0)
{
selectedIndex = 0;
}
else
{
selectedIndex += 1;
if (selectedIndex >= m_dataTypeMenu.GetProxyModel()->rowCount())
{
selectedIndex = 0;
}
}
m_dataTypeMenu.SetSelectedRow(selectedIndex);
AZ::TypeId typeId = m_dataTypeMenu.GetSelectedTypeId();
AZStd::string typeName = m_dataTypeMenu.GetModel()->FindTypeNameForTypeId(typeId);
if (!typeName.empty() && !typeId.IsNull())
{
m_ui->variableType->setText(typeName.c_str());
m_ui->variableType->setSelection(0, static_cast<int>(typeName.size()));
m_completer.setCompletionPrefix(typeName.c_str());
}
return true;
}
else if (keyEvent->key() == Qt::Key_Up)
{
if (m_dataTypeMenu.isHidden())
{
m_dataTypeMenu.GetProxyModel()->SetFilter("");
DisplayMenu();
}
int selectedIndex = m_dataTypeMenu.GetSelectedRow();
if (selectedIndex < 0)
{
selectedIndex = m_dataTypeMenu.GetProxyModel()->rowCount() - 1;
}
else
{
selectedIndex -= 1;
if (selectedIndex < 0)
{
selectedIndex = m_dataTypeMenu.GetProxyModel()->rowCount() - 1;
}
}
m_dataTypeMenu.SetSelectedRow(selectedIndex);
AZ::TypeId typeId = m_dataTypeMenu.GetSelectedTypeId();
AZStd::string typeName = m_dataTypeMenu.GetModel()->FindTypeNameForTypeId(typeId);
if (!typeName.empty() && !typeId.IsNull())
{
m_ui->variableType->setText(typeName.c_str());
m_ui->variableType->setSelection(0, static_cast<int>(typeName.size()));
m_completer.setCompletionPrefix(typeName.c_str());
}
return true;
}
else if (keyEvent->key() == Qt::Key_Escape)
{
DisplayType(m_lastId);
}
}
default:
break;
}
}
return false;
}
void ContainerTypeLineEdit::OnTextChanged()
{
DisplayMenu();
UpdateFilter();
}
void ContainerTypeLineEdit::OnOptionsClicked()
{
if (m_dataTypeMenu.isHidden())
{
m_dataTypeMenu.GetProxyModel()->SetFilter("");
DisplayMenu();
}
else
{
m_dataTypeMenu.accept();
}
}
void ContainerTypeLineEdit::OnReturnPressed()
{
const bool allowReset = false;
if (SubmitData(allowReset))
{
m_dataTypeMenu.accept();
}
else
{
m_ui->variableType->setText("");
UpdateFilter();
}
// When we press enter, we will also get an editing complete signal. We want to ignore that since we handled it here.
m_ignoreNextComplete = true;
}
void ContainerTypeLineEdit::OnEditComplete()
{
if (m_ignoreNextComplete)
{
m_ignoreNextComplete = false;
return;
}
SubmitData();
QTimer::singleShot(0, [this]() { m_dataTypeMenu.reject(); });
}
void ContainerTypeLineEdit::UpdateFilter()
{
m_dataTypeMenu.GetProxyModel()->SetFilter(GetUserInputText());
}
bool ContainerTypeLineEdit::SubmitData(bool allowReset)
{
AZStd::string typeName = m_ui->variableType->text().toUtf8().data();
AZ::TypeId typeId = m_dataTypeMenu.GetModel()->FindTypeIdForTypeName(typeName);
// We didn't input a valid type. So default to our last previously known value.
if (typeId == azrtti_typeid<void>())
{
if (allowReset)
{
DisplayType(m_lastId);
typeId = m_lastId;
}
}
else if (typeId != m_lastId)
{
SelectType(typeId);
}
return typeId != azrtti_typeid<void>();
}
void ContainerTypeLineEdit::DisplayMenu()
{
if (!m_recursionBlocker)
{
QScopedValueRollback<bool> valueRollback(m_recursionBlocker, true);
if (m_dataTypeMenu.isHidden())
{
m_dataTypeMenu.ShowMenu();
QRect dialogGeometry = m_dataTypeMenu.geometry();
dialogGeometry.moveTopLeft(m_ui->variableType->mapToGlobal(QPoint(0, m_ui->variableType->height())));
dialogGeometry.setWidth(m_ui->variableType->width());
m_dataTypeMenu.setGeometry(dialogGeometry);
}
}
if (!m_disableHidingStateSetter.HasState())
{
m_disableHidingStateSetter.SetState(true);
}
}
QString ContainerTypeLineEdit::GetUserInputText()
{
QString lineEditText = m_ui->variableType->text();
// The QCompleter doesn't seem to update the completion prefix when you delete anything, only when things are added.
// To get it to update correctly when the user deletes something, I'm using the combination of things:
//
// 1) If we have a completion, that text will be auto filled into the quick filter because of the completion model.
// So, we will compare those two values, and if they match, we know we want to search using the completion prefix.
//
// 2) If they don't match, it means that user deleted something, and the Completer didn't update it's internal state, so we'll just
// use whatever is in the text box.
//
// 3) When the text field is set to empty, the current completion gets invalidated, but the prefix doesn't, so that gets special cased out.
//
// Extra fun: If you type in something, "Like" then delete a middle character, "Lie", and then put the k back in. It will auto complete the E
// visually but the completion prefix will be the entire word.
if (m_ui->variableType->completer()
&& m_ui->variableType->completer()->currentCompletion().compare(lineEditText, Qt::CaseInsensitive) == 0
&& !lineEditText.isEmpty())
{
lineEditText = m_ui->variableType->completer()->completionPrefix();
}
return lineEditText;
}
}
#include <Editor/View/Dialogs/ContainerWizard/moc_ContainerTypeLineEdit.cpp>
@@ -0,0 +1,156 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QCompleter>
#include <QDialog>
#include <QMenu>
#include <QTableView>
#include <qtimer.h>
#include <qpixmap.h>
#include <QWidget>
#include <AzCore/Memory/SystemAllocator.h>
#include <Editor/View/Widgets/DataTypePalette/DataTypePaletteModel.h>
#include <GraphCanvas/Utils/StateControllers/StackStateController.h>
#endif
namespace Ui
{
class ContainerTypeLineEdit;
class ContainerTypeComboBox;
}
namespace ScriptCanvasEditor
{
class ContainerTypeMenu
: public QDialog
{
Q_OBJECT
public:
ContainerTypeMenu(QWidget* parent = nullptr);
~ContainerTypeMenu() override;
DataTypePaletteModel* GetModel();
const DataTypePaletteModel* GetModel() const;
DataTypePaletteSortFilterProxyModel* GetProxyModel();
const DataTypePaletteSortFilterProxyModel* GetProxyModel() const;
void ShowMenu();
void HideMenu();
void reject() override;
bool eventFilter(QObject* object, QEvent* event) override;
void focusInEvent(QFocusEvent* focusEvent) override;
void focusOutEvent(QFocusEvent* focusEvent) override;
void showEvent(QShowEvent* showEvent) override;
void hideEvent(QHideEvent* hideEvent) override;
GraphCanvas::StateController<bool>* GetStateController();
void SetSelectedRow(int row);
int GetSelectedRow() const;
AZ::TypeId GetSelectedTypeId() const;
void OnTableClicked(const QModelIndex& modelIndex);
Q_SIGNALS:
void ContainerTypeSelected(const AZ::TypeId& typeId);
void VisibilityChanged(bool visibility);
private:
void HandleFocusIn();
void HandleFocusOut();
QTableView m_tableView;
DataTypePaletteSortFilterProxyModel m_proxyModel;
DataTypePaletteModel m_model;
GraphCanvas::StateSetter<bool> m_disableHidingStateSetter;
GraphCanvas::StackStateController<bool> m_disableHiding;
bool m_ignoreNextFocusIn;
};
class ContainerTypeLineEdit
: public QWidget
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(ContainerTypeLineEdit, AZ::SystemAllocator, 0);
ContainerTypeLineEdit(int index, QWidget* parent = nullptr);
~ContainerTypeLineEdit();
void SetDisplayName(AZStd::string_view name);
void SetDataTypes(const AZStd::unordered_set< AZ::TypeId >& dataTypes);
AZ::TypeId GetDefaultTypeId() const;
void SelectType(const AZ::TypeId& typeId);
bool DisplayType(const AZ::TypeId& typeId);
QWidget* GetLineEdit() const;
void ResetLineEdit();
void CancelDataInput();
void HideDataTypeMenu();
Q_SIGNALS:
void TypeChanged(int index, const AZ::TypeId& typeId);
void DataTypeMenuVisibilityChanged(bool visible);
protected:
bool eventFilter(QObject* obj, QEvent* event);
void OnTextChanged();
void OnOptionsClicked();
void OnReturnPressed();
void OnEditComplete();
void UpdateFilter();
private:
bool SubmitData(bool allowReset = true);
void DisplayMenu();
QString GetUserInputText();
AZStd::unique_ptr<Ui::ContainerTypeLineEdit> m_ui;
QTimer m_filterTimer;
bool m_ignoreNextComplete;
bool m_recursionBlocker;
int m_index;
AZ::TypeId m_lastId;
const QPixmap* m_iconPixmap;
QCompleter m_completer;
ContainerTypeMenu m_dataTypeMenu;
GraphCanvas::StateSetter<bool> m_disableHidingStateSetter;
};
}
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ContainerTypeLineEdit</class>
<widget class="QWidget" name="ContainerTypeLineEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>462</width>
<height>368</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<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="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</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="nameDisplay">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>115</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Specifies the type of Container to Create.</string>
</property>
<property name="text">
<string>Key Type</string>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="iconLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="variableType"/>
</item>
</layout>
</widget>
<resources>
<include location="../../Windows/ScriptCanvasEditorResources.qrc"/>
</resources>
<connections/>
</ui>
@@ -0,0 +1,622 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <precompiled.h>
#include <AzCore/Serialization/Utils.h>
#include <AzCore/ScriptCanvas/ScriptCanvasOnDemandNames.h>
#include <Editor/View/Dialogs/ContainerWizard/ContainerWizard.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <Editor/View/Dialogs/ContainerWizard/ui_ContainerWizard.h>
AZ_POP_DISABLE_WARNING
#include <Editor/Include/ScriptCanvas/GraphCanvas/NodeDescriptorBus.h>
#include <AzCore/UserSettings/UserSettings.h>
#include <Editor/View/Dialogs/ContainerWizard/ContainerTypeLineEdit.h>
#include <Editor/View/Widgets/VariablePanel/VariableDockWidget.h>
#include <Editor/Settings.h>
#include <Editor/Translation/TranslationHelper.h>
#include <ScriptCanvas/Data/Data.h>
#include <ScriptCanvas/Variable/VariableBus.h>
namespace ScriptCanvasEditor
{
////////////////////
// ContainerWizard
////////////////////
ContainerWizard::ContainerWizard(QWidget* parent)
: QDialog(parent, Qt::FramelessWindowHint)
, m_serializeContext(nullptr)
, m_validationAction(nullptr)
, m_invalidIcon(":/ScriptCanvasEditorResources/Resources/error_icon.png")
, m_dataTypeMenuVisibile(false)
, m_releaseVariable(false)
, m_variableCounter(0)
, m_ui(new Ui::ContainerWizard())
{
m_ui->setupUi(this);
QObject::connect(m_ui->containerTypeBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ContainerWizard::OnContainerTypeChanged);
m_ui->containerTypeBox->setEditable(false);
// Don't want to enable enter triggering through the default mechanism for the create/cancel, since it causes a bunch of accidental triggers
// of submission while editing. Instead install an event filter and deal with this internally.
m_ui->createButton->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
m_ui->createButton->setAutoDefault(false);
m_ui->createButton->setDefault(false);
m_ui->createButton->installEventFilter(this);
m_ui->cancelButton->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
m_ui->cancelButton->setAutoDefault(false);
m_ui->cancelButton->setDefault(false);
m_ui->cancelButton->installEventFilter(this);
QObject::connect(m_ui->createButton, &QPushButton::clicked, this, &ContainerWizard::OnCreate);
QObject::connect(m_ui->cancelButton, &QPushButton::clicked, this, &ContainerWizard::OnCancel);
QObject::connect(this, &QDialog::finished, this, &ContainerWizard::OnFinished);
QObject::connect(m_ui->variableName, &QLineEdit::textChanged, this, &ContainerWizard::ValidateName);
}
ContainerWizard::~ContainerWizard()
{
ClearDisplay();
for (ContainerTypeLineEdit* lineEdit : m_containerTypeLineEdit)
{
delete lineEdit;
}
}
void ContainerWizard::SetActiveScriptCanvasId(const ScriptCanvas::ScriptCanvasId& scriptCanvasId)
{
m_activeScriptCanvasId = scriptCanvasId;
}
void ContainerWizard::RegisterType(const AZ::TypeId& dataType)
{
if (AZ::Utils::IsContainerType(dataType))
{
RegisterContainerType(dataType);
}
else
{
RegisterDataType(dataType);
}
}
void ContainerWizard::ShowWizard(const AZ::TypeId& genericContainerType)
{
// Always default the wizard to the unchecked state
m_ui->checkBox->setChecked(false);
if (m_ui->containerTypeBox->count() != m_genericContainerTypes.size())
{
QSignalBlocker signalBlock(m_ui->containerTypeBox);
std::sort(m_genericContainerTypeNames.begin(), m_genericContainerTypeNames.end(), [](const AZStd::pair< AZStd::string, AZ::TypeId>& lhs,
const AZStd::pair< AZStd::string, AZ::TypeId>& rhs)
{
return AZStd::less<AZStd::string>()(lhs.first, rhs.first);
});
m_ui->containerTypeBox->clear();
for (const auto& element : m_genericContainerTypeNames)
{
m_ui->containerTypeBox->addItem(element.first.c_str());
}
}
for (int i = 0; i < m_genericContainerTypeNames.size(); ++i)
{
const auto& element = m_genericContainerTypeNames[i];
if (element.second == genericContainerType)
{
QSignalBlocker signalBlock(m_ui->containerTypeBox);
m_ui->containerTypeBox->setCurrentIndex(i);
}
}
// Need to show before trying to initialize the display otherwise the line edits won't be cleaned up
// correctly.
show();
InitializeDisplay(genericContainerType);
m_releaseVariable = true;
bool nameAvailable = false;
AZStd::string variableName;
do
{
SceneCounterRequestBus::EventResult(m_variableCounter, m_activeScriptCanvasId, &SceneCounterRequests::GetNewVariableCounter);
variableName = VariableDockWidget::ConstructDefaultVariableName(m_variableCounter);
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(nameAvailable, m_activeScriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::IsNameAvailable, variableName);
} while (!nameAvailable);
m_ui->variableName->setText(variableName.c_str());
m_ui->variableName->setFocus(Qt::FocusReason::MouseFocusReason);
m_ui->variableName->setSelection(0, m_ui->variableName->text().size());
}
void ContainerWizard::accept()
{
QDialog::accept();
}
void ContainerWizard::reject()
{
if (m_dataTypeMenuVisibile)
{
for (ContainerTypeLineEdit* lineEdit : m_containerTypeLineEdit)
{
lineEdit->HideDataTypeMenu();
}
m_dataTypeMenuVisibile = false;
}
else
{
QDialog::reject();
}
}
void ContainerWizard::hideEvent(QHideEvent* hideEvent)
{
QDialog::hideEvent(hideEvent);
for (ContainerTypeLineEdit* lineEdit : m_containerTypeLineEdit)
{
lineEdit->HideDataTypeMenu();
}
m_dataTypeMenuVisibile = false;
}
bool ContainerWizard::eventFilter(QObject* object, QEvent* event)
{
if (object == m_ui->createButton
|| object == m_ui->cancelButton)
{
if (event->type() == QEvent::Type::KeyRelease)
{
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Enter
|| keyEvent->key() == Qt::Key_Return)
{
QPushButton* button = qobject_cast<QPushButton*>(object);
if (button)
{
button->click();
}
}
}
}
return false;
}
const AZStd::unordered_map<AZ::Crc32, AZ::TypeId>& ContainerWizard::GetFinalTypeMapping() const
{
return m_finalContainerTypeIds;
}
void ContainerWizard::ReparseDisplay()
{
AZ::Crc32 workingCrc = AZ::Crc32(m_genericType.ToString<AZStd::string>().c_str());
for (int typeIndex = 0; typeIndex < m_containerTypes.size(); ++typeIndex)
{
const AZ::TypeId& typeId = m_containerTypes[typeIndex];
ContainerTypeLineEdit* lineEdit = GetLineEdit(typeIndex);
auto dataTypeIter = m_containerDataTypeSets.find(workingCrc);
if (dataTypeIter == m_containerDataTypeSets.end())
{
// No idea wtf do here we've managed to put ourselves into an invalid state
AZ_Error("ScriptCanvas", false, "Unknown partial type found in Container Creation. Aborting.");
close();
break;
}
lineEdit->SetDataTypes(dataTypeIter->second);
AZ::TypeId selectedTypeId = typeId;
{
QSignalBlocker signalBlocker(lineEdit);
if (!lineEdit->DisplayType(typeId))
{
selectedTypeId = lineEdit->GetDefaultTypeId();
lineEdit->DisplayType(typeId);
}
}
m_containerTypes[typeIndex] = selectedTypeId;
workingCrc.Add(selectedTypeId.ToString<AZStd::string>().c_str());
}
}
void ContainerWizard::OnCreate()
{
AZ::Crc32 typeCrc = AZ::Crc32(m_genericType.ToString<AZStd::string>().c_str());
for (const AZ::TypeId& typeId : m_containerTypes)
{
typeCrc.Add(typeId.ToString<AZStd::string>().c_str());
}
auto containerIter = m_finalContainerTypeIds.find(typeCrc);
if (containerIter != m_finalContainerTypeIds.end())
{
m_releaseVariable = false;
AZStd::string variableName = m_ui->variableName->text().toUtf8().data();
if (m_ui->checkBox->isChecked())
{
AZStd::intrusive_ptr<EditorSettings::ScriptCanvasEditorSettings> settings = AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
if (settings)
{
auto insertResult = settings->m_pinnedDataTypes.insert(containerIter->second);
if (insertResult.second)
{
Q_EMIT ContainerPinned(containerIter->second);
}
}
}
Q_EMIT CreateContainerVariable(variableName, containerIter->second);
close();
}
else
{
AZ_Warning("ScriptCanvas", false, "Unable to find Registered type with the given parameters.");
}
}
void ContainerWizard::OnCancel()
{
close();
}
void ContainerWizard::OnFinished([[maybe_unused]] int result)
{
ClearDisplay();
if (m_releaseVariable)
{
SceneCounterRequestBus::Event(m_activeScriptCanvasId, &SceneCounterRequests::ReleaseVariableCounter, m_variableCounter);
}
}
void ContainerWizard::OnContainerTypeChanged(int index)
{
if (index >= 0 && index < m_genericContainerTypeNames.size())
{
InitializeDisplay(m_genericContainerTypeNames[index].second);
}
}
void ContainerWizard::OnTypeChanged(int index, const AZ::TypeId& typeId)
{
if (index >= 0 && index < m_containerTypes.size())
{
m_containerTypes[index] = typeId;
ReparseDisplay();
}
}
void ContainerWizard::OnDataTypeMenuVisibilityChanged(bool visible)
{
m_dataTypeMenuVisibile = visible;
}
void ContainerWizard::ValidateName(const QString& newName)
{
if (m_validationAction)
{
m_ui->variableName->removeAction(m_validationAction);
delete m_validationAction;
m_validationAction = nullptr;
}
ScriptCanvas::VariableValidationOutcome validName = AZ::Failure(ScriptCanvas::GraphVariableValidationErrorCode::Unknown);
ScriptCanvas::GraphVariableManagerRequestBus::EventResult(validName, m_activeScriptCanvasId, &ScriptCanvas::GraphVariableManagerRequests::IsNameValid, newName.toUtf8().data());
if (!validName || newName.isEmpty())
{
m_validationAction = m_ui->variableName->addAction(m_invalidIcon, QLineEdit::TrailingPosition);
if (validName.GetError() == ScriptCanvas::GraphVariableValidationErrorCode::Invalid)
{
m_validationAction->setToolTip("A Variable name cannot be empty or over 200 characters.\nPlease specify a new name for the variable.");
}
else if (validName.GetError() == ScriptCanvas::GraphVariableValidationErrorCode::Duplicate)
{
m_validationAction->setToolTip("This name is already in use by\nanother variable");
}
}
m_ui->createButton->setEnabled((validName && !newName.isEmpty()));
}
void ContainerWizard::ClearDisplay()
{
m_containerTypes.clear();
while (m_ui->typeSelectionFrame->layout()->count() > 0)
{
QLayoutItem* layoutItem = m_ui->typeSelectionFrame->layout()->takeAt(0);
}
for (ContainerTypeLineEdit* lineEdit : m_containerTypeLineEdit)
{
if (lineEdit->isVisible())
{
lineEdit->ResetLineEdit();
lineEdit->setVisible(false);
}
else
{
break;
}
}
}
void ContainerWizard::InitializeDisplay(const AZ::TypeId& typeId)
{
m_genericType = typeId;
if (AZ::Utils::IsMapContainerType(m_genericType))
{
PopulateMapDisplay();
}
else
{
PopulateGeneralDisplay();
}
adjustSize();
}
void ContainerWizard::PopulateMapDisplay()
{
const AZStd::vector< AZStd::string > typeLabels = { "Key", "Value" };
PopulateGeneralDisplay("Map %i", "Map", typeLabels);
}
void ContainerWizard::PopulateGeneralDisplay(const AZStd::string& patternFallback, const AZStd::string& singleTypeString, const AZStd::vector< AZStd::string >& typeLabels)
{
ClearDisplay();
AZ::Crc32 workingCrc = AZ::Crc32(m_genericType.ToString<AZStd::string>().c_str());
int containerIndex = 0;
auto dataTypeIter = m_containerDataTypeSets.find(workingCrc);
QWidget* focusWidget = m_ui->variableName;
while (dataTypeIter != m_containerDataTypeSets.end())
{
DataTypeSet& dataTypeSet = dataTypeIter->second;
ContainerTypeLineEdit* lineEdit = GetLineEdit(containerIndex);
lineEdit->ResetLineEdit();
if (containerIndex >= typeLabels.size())
{
AZStd::string containerName = AZStd::string::format(patternFallback.c_str(), containerIndex);
lineEdit->SetDisplayName(containerName);
}
else
{
lineEdit->SetDisplayName(typeLabels[containerIndex]);
}
lineEdit->SetDataTypes(dataTypeSet);
lineEdit->setVisible(true);
m_ui->typeSelectionFrame->layout()->addWidget(lineEdit);
AZ::TypeId typeId = lineEdit->GetDefaultTypeId();
workingCrc.Add(typeId.ToString<AZStd::string>().c_str());
m_containerTypes.emplace_back(typeId);
{
QSignalBlocker signalBlocker(lineEdit);
lineEdit->DisplayType(typeId);
}
QWidget* nextFocus = lineEdit->GetLineEdit();
setTabOrder(focusWidget, nextFocus);
focusWidget = nextFocus;
++containerIndex;
dataTypeIter = m_containerDataTypeSets.find(workingCrc);
}
setTabOrder(focusWidget, m_ui->createButton);
if (containerIndex == 1)
{
ContainerTypeLineEdit* lineEdit = GetLineEdit(0);
lineEdit->SetDisplayName(singleTypeString);
}
}
void ContainerWizard::RegisterDataType(const AZ::TypeId& dataType)
{
m_dataTypes[dataType] = ScriptCanvasEditor::TranslationHelper::GetSafeTypeName(ScriptCanvas::Data::FromAZType(dataType));
}
void ContainerWizard::RegisterContainerType(const AZ::TypeId& containerType)
{
if (m_serializeContext == nullptr)
{
AZ::ComponentApplicationBus::BroadcastResult(m_serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
if (m_serializeContext == nullptr)
{
AZ_Warning("ScriptCanvas", false, "Not given a SerializeContext and unable to find a SerializeContext to deduce generic ContainerTypes from.");
}
}
AZStd::vector<AZ::Uuid> containedTypes = AZ::Utils::GetContainedTypes(containerType);
AZ::GenericClassInfo* classInfo = m_serializeContext->FindGenericClassInfo(containerType);
if (classInfo)
{
// Until we get the ability to create generic versions of these containers
// Keep track of all of the partial matches so we can generate various lists in order to pretend
// that we have general Key/Value support.
//
// Using the Partial CRC to identify a partial match so we can sort of soft fill out our template by
// knowing all of the possible outcomes given Container X with first element Y
AZ::Crc32 workingCrc = AZ::Crc32(classInfo->GetGenericTypeId().ToString<AZStd::string>().c_str());
for (const AZ::Uuid& containedType : containedTypes)
{
DataTypeSet& dataTypeSet = m_containerDataTypeSets[workingCrc];
if (ScriptCanvas::Data::IsNumber(containedType))
{
dataTypeSet.insert(azrtti_typeid<ScriptCanvas::Data::NumberType>());
workingCrc.Add(containedType.ToString<AZStd::string>().c_str());
}
else
{
dataTypeSet.insert(containedType);
workingCrc.Add(containedType.ToString<AZStd::string>().c_str());
}
}
if (m_finalContainerTypeIds.find(workingCrc) == m_finalContainerTypeIds.end())
{
m_finalContainerTypeIds[workingCrc] = containerType;
}
// Need to populate the combo box
AZ::TypeId genericTypeId = AZ::Utils::GetGenericContainerType(containerType);
auto insertResult = m_genericContainerTypes.insert(genericTypeId);
if (insertResult.second)
{
AZ::BehaviorContext* behaviorContext = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(behaviorContext, &AZ::ComponentApplicationRequests::GetBehaviorContext);
if (behaviorContext)
{
auto mapIter = behaviorContext->m_typeToClassMap.find(containerType);
if (mapIter != behaviorContext->m_typeToClassMap.end())
{
AZ::Attribute* categoryAttribute = AZ::FindAttribute(AZ::Script::Attributes::Category, mapIter->second->m_attributes);
AZStd::string categoryName;
if (categoryAttribute)
{
if (AZ::AttributeReader(nullptr, categoryAttribute).Read<AZStd::string>(categoryName, *behaviorContext))
{
m_genericContainerTypeNames.emplace_back(categoryName, genericTypeId);
}
else
{
m_genericContainerTypes.erase(genericTypeId);
}
}
AZ::Attribute* tooltipAttribute = AZ::FindAttribute(AZ::Script::Attributes::ToolTip, mapIter->second->m_attributes);
if (tooltipAttribute)
{
AZStd::string containerToolTip;
if (AZ::AttributeReader(nullptr, tooltipAttribute).Read<AZStd::string>(containerToolTip, *behaviorContext))
{
QString toolTip = m_ui->containerLabel->toolTip();
// We want to sort the container tool tips so the order they are added matches the order in which
// we display them in the combobox.
//
// I don't really have a final point at which to resolve this currently, so I'm just going to sort the elements on the
// fly with a ton of string manipulation to get it to align correctly.
QStringList previousToolTips = toolTip.split("\n");
if (!previousToolTips.empty())
{
toolTip.clear();
// First tooltip is always the native tool tip. So we want to maintain that
toolTip.append(previousToolTips[0]);
previousToolTips.removeFirst();
QString newToolTip = QString(" %1 - %2").arg(categoryName.c_str()).arg(containerToolTip.c_str());
previousToolTips.push_back(newToolTip);
previousToolTips.sort(Qt::CaseInsensitive);
for (const QString& toolTipString : previousToolTips)
{
toolTip.append("\n");
toolTip.append(toolTipString);
}
m_ui->containerLabel->setToolTip(toolTip);
}
}
}
}
}
}
}
else
{
AZ_Warning("ScriptCanvas", false, "Could not find generic class info for container with TypeId(%s)", containerType.ToString<AZStd::string>().c_str());
}
}
ContainerTypeLineEdit* ContainerWizard::GetLineEdit(int typeIndex)
{
while (m_containerTypeLineEdit.size() <= typeIndex)
{
ContainerTypeLineEdit* lineEdit = aznew ContainerTypeLineEdit(typeIndex, this);
QObject::connect(lineEdit, &ContainerTypeLineEdit::TypeChanged, this, &ContainerWizard::OnTypeChanged);
QObject::connect(lineEdit, &ContainerTypeLineEdit::DataTypeMenuVisibilityChanged, this, &ContainerWizard::OnDataTypeMenuVisibilityChanged);
m_containerTypeLineEdit.emplace_back(lineEdit);
}
return m_containerTypeLineEdit[typeIndex];
}
}
#include <Editor/View/Dialogs/ContainerWizard/moc_ContainerWizard.cpp>
@@ -0,0 +1,128 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/PlatformDef.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <QDialog>
#include <QIcon>
AZ_POP_DISABLE_WARNING
#include <AzCore/Component/EntityId.h>
#include <AzCore/Math/Uuid.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/containers/unordered_map.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <ScriptCanvas/Core/Core.h>
#endif
namespace Ui
{
class ContainerWizard;
}
namespace ScriptCanvasEditor
{
class ContainerTypeLineEdit;
class ContainerWizard
: public QDialog
{
Q_OBJECT
private:
typedef AZStd::unordered_set< AZ::TypeId > DataTypeSet;
public:
AZ_CLASS_ALLOCATOR(ContainerWizard, AZ::SystemAllocator, 0);
ContainerWizard(QWidget* parent = nullptr);
~ContainerWizard() override;
void SetActiveScriptCanvasId(const ScriptCanvas::ScriptCanvasId& scriptCanvasId);
void RegisterType(const AZ::TypeId& dataType);
void ShowWizard(const AZ::TypeId& genericContainerType);
void accept() override;
void reject() override;
void hideEvent(QHideEvent* hideEvent) override;
bool eventFilter(QObject* object, QEvent* event) override;
const AZStd::unordered_map< AZ::Crc32, AZ::TypeId >& GetFinalTypeMapping() const;
public Q_SLOTS:
void ReparseDisplay();
void OnFinished(int result);
void OnContainerTypeChanged(int index);
void OnTypeChanged(int index, const AZ::TypeId& typeId);
void OnDataTypeMenuVisibilityChanged(bool visible);
void ValidateName(const QString& newName);
Q_SIGNALS:
void ContainerPinned(const AZ::TypeId& typeId);
void CreateContainerVariable(const AZStd::string& variableName, const AZ::TypeId& typeId);
protected:
void OnCreate();
void OnCancel();
void ClearDisplay();
void InitializeDisplay(const AZ::TypeId& typeId);
void PopulateMapDisplay();
void PopulateGeneralDisplay(const AZStd::string& patternFallback = "Type %i", const AZStd::string& singleTypeString = "Type", const AZStd::vector< AZStd::string >& typeLabels = AZStd::vector< AZStd::string>());
private:
void RegisterDataType(const AZ::TypeId& dataType);
void RegisterContainerType(const AZ::TypeId& containerType);
ContainerTypeLineEdit* GetLineEdit(int paramIndex);
AZ::SerializeContext* m_serializeContext;
ScriptCanvas::ScriptCanvasId m_activeScriptCanvasId;
QAction* m_validationAction;
QIcon m_invalidIcon;
bool m_dataTypeMenuVisibile;
bool m_releaseVariable;
AZ::u32 m_variableCounter;
AZ::TypeId m_genericType;
AZStd::vector< AZ::TypeId > m_containerTypes;
AZStd::vector< ContainerTypeLineEdit* > m_containerTypeLineEdit;
DataTypeSet m_genericContainerTypes;
AZStd::vector< AZStd::pair<AZStd::string, AZ::TypeId> > m_genericContainerTypeNames;
// Temporarily unused. When we can reflect combinations on demand, we can use this list to populate, rather then the pre-generated lists
AZStd::unordered_map< AZ::TypeId, AZStd::string > m_dataTypes;
AZStd::unordered_map< AZ::Crc32, DataTypeSet > m_containerDataTypeSets;
AZStd::unordered_map< AZ::Crc32, AZ::TypeId > m_finalContainerTypeIds;
AZStd::unique_ptr< Ui::ContainerWizard > m_ui;
};
}
@@ -0,0 +1,358 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ContainerWizard</class>
<widget class="QDialog" name="ContainerWizard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>404</width>
<height>214</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>350</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Create Container</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="sizeConstraint">
<enum>QLayout::SetFixedSize</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QFrame" name="frame_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>115</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Variable Name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="variableName"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<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="containerLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>115</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Specifies the type of Container to create.</string>
</property>
<property name="text">
<string>Container Type</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="containerTypeBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="minimumSize">
<size>
<width>330</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="typeSelectionFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<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>
</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>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<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="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>115</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Pin To Variable List</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBox">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<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>
</widget>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<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="createButton">
<property name="text">
<string>Create</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,56 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "NewGraphDialog.h"
#include <QLineEdit>
#include <QPushButton>
#include "Editor/View/Dialogs/ui_NewGraphDialog.h"
namespace ScriptCanvasEditor
{
NewGraphDialog::NewGraphDialog(const QString& title, const QString& text, QWidget* pParent /*=nullptr*/)
: QDialog(pParent)
, ui(new Ui::NewGraphDialog)
, m_text(text)
{
ui->setupUi(this);
setWindowTitle(title);
QObject::connect(ui->GraphName, &QLineEdit::returnPressed, this, &NewGraphDialog::OnOK);
QObject::connect(ui->GraphName, &QLineEdit::textChanged, this, &NewGraphDialog::OnTextChanged);
QObject::connect(ui->ok, &QPushButton::clicked, this, &NewGraphDialog::OnOK);
QObject::connect(ui->cancel, &QPushButton::clicked, this, &QDialog::reject);
ui->ok->setEnabled(false);
}
void NewGraphDialog::OnTextChanged(const QString& text)
{
ui->ok->setEnabled(!text.isEmpty());
}
void NewGraphDialog::OnOK()
{
QString itemName = ui->GraphName->text();
m_text = itemName.toLocal8Bit().constData();
accept();
}
#include <Editor/View/Dialogs/moc_NewGraphDialog.cpp>
}
@@ -0,0 +1,46 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QDialog>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#endif
namespace Ui
{
class NewGraphDialog;
}
namespace ScriptCanvasEditor
{
class NewGraphDialog
: public QDialog
{
Q_OBJECT
public:
NewGraphDialog(const QString& title, const QString& text, QWidget* pParent = nullptr);
const QString& GetText() const { return m_text; }
protected:
void OnOK();
void OnTextChanged(const QString& text);
QString m_text;
Ui::NewGraphDialog* ui;
};
}
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NewGraphDialog</class>
<widget class="QDialog" name="NewGraphDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>300</width>
<height>72</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="name">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="GraphName">
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<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>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="ok">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,224 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "Settings.h"
// qtextformat.h(365): warning C4251: 'QTextFormat::d': class 'QSharedDataPointer<QTextFormatPrivate>' needs to have dll-interface to be used by clients of class 'QTextFormat'
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option")
#include <QLineEdit>
#include <QPushButton>
#include <QKeyEvent>
AZ_POP_DISABLE_WARNING
#include <AzCore/UserSettings/UserSettingsComponent.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
#include <GraphCanvas/Editor/AssetEditorBus.h>
#include <Editor/GraphCanvas/GraphCanvasEditorNotificationBusId.h>
#include "Editor/View/Dialogs/ui_Settings.h"
namespace ScriptCanvasEditor
{
SettingsDialog::SettingsDialog(const QString& title, ScriptCanvas::ScriptCanvasId scriptCanvasId, QWidget* pParent /*=nullptr*/)
: QDialog(pParent)
, ui(new Ui::SettingsDialog)
, m_scriptCanvasId(scriptCanvasId)
{
ui->setupUi(this);
setWindowTitle(title);
QObject::connect(ui->ok, &QPushButton::clicked, this, &SettingsDialog::OnOK);
QObject::connect(ui->cancel, &QPushButton::clicked, this, &SettingsDialog::OnCancel);
if (m_scriptCanvasId.IsValid())
{
SetType(SettingsType::Graph);
}
else
{
SetType(SettingsType::General);
}
m_revertOnClose = true;
}
void SettingsDialog::ConfigurePropertyEditor(AzToolsFramework::ReflectedPropertyEditor* editor)
{
editor->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
editor->SetHideRootProperties(false);
editor->SetDynamicEditDataProvider(nullptr);
editor->ExpandAll();
editor->InvalidateAll();
}
SettingsDialog::~SettingsDialog()
{
if (m_revertOnClose)
{
RevertSettings();
}
ui->propertyEditor->ClearInstances();
}
void SettingsDialog::OnTextChanged(const QString& text)
{
ui->ok->setEnabled(!text.isEmpty());
}
void SettingsDialog::OnOK()
{
m_revertOnClose = false;
AZ::UserSettingsOwnerRequestBus::Event(AZ::UserSettings::CT_LOCAL, &AZ::UserSettingsOwnerRequests::SaveSettings);
GraphCanvas::AssetEditorSettingsNotificationBus::Event(ScriptCanvasEditor::AssetEditorId, &GraphCanvas::AssetEditorSettingsNotifications::OnSettingsChanged);
accept();
}
void Settings::Reflect(AZ::ReflectContext* reflection)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
if (serializeContext)
{
serializeContext->Class<Settings>()
->Version(0)
->Field("EnableLogging", &Settings::m_enableLogging)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Settings>("Script Canvas Settings", "Per-graph Script Canvas settings")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ_CRC("PropertyVisibility_ShowChildrenOnly", 0xef428f20))
->DataElement(AZ::Edit::UIHandlers::Default, &Settings::m_enableLogging, "Logging", "Will enable logging for this Script Canvas graph")
;
}
}
}
void SettingsDialog::OnCancel()
{
RevertSettings();
close();
}
void SettingsDialog::SetType(SettingsType settingsType)
{
AZ::SerializeContext* context = nullptr;
{
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationRequests::GetSerializeContext);
AZ_Assert(context, "We should have a valid context!");
}
AZ_Warning("SetingsDialog", settingsType != SettingsType::None,
"Cannot set up settings for None type. Please choose a valid type.");
// SettingsType::None
ui->generalLabel->setVisible(false);
ui->previewSettingsPropertyEditor->setVisible(false);
ui->previewSettingsPropertyEditor->SetAutoResizeLabels(true);
ui->graphLabel->setVisible(false);
ui->propertyEditor->setVisible(false);
ui->propertyEditor->SetAutoResizeLabels(true);
if (settingsType == SettingsType::Graph || settingsType == SettingsType::All)
{
ui->graphLabel->setVisible(true);
ui->propertyEditor->setVisible(true);
SetupGraphSettings(context);
}
if (settingsType == SettingsType::General || settingsType == SettingsType::All)
{
ui->generalLabel->setVisible(true);
ui->previewSettingsPropertyEditor->setVisible(true);
SetupGeneralSettings(context);
}
m_settingsType = settingsType;
}
void SettingsDialog::SetupGeneralSettings(AZ::SerializeContext* context)
{
// General properties
AZStd::intrusive_ptr<EditorSettings::ScriptCanvasEditorSettings> previewSettings =
AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(
AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
// Store a copy to revert if needed.
m_originalEditorSettings = *previewSettings;
ui->previewSettingsPropertyEditor->Setup(context, nullptr, false, 210);
ui->previewSettingsPropertyEditor->AddInstance(previewSettings.get(), previewSettings->RTTI_GetType());
ui->previewSettingsPropertyEditor->setObjectName("ui->previewSettingsPropertyEditor");
ConfigurePropertyEditor(ui->previewSettingsPropertyEditor);
}
void SettingsDialog::SetupGraphSettings(AZ::SerializeContext* context)
{
if (m_scriptCanvasId.IsValid())
{
AZStd::intrusive_ptr<Settings> settings =
AZ::UserSettings::CreateFind<Settings>(AZ::Crc32(m_scriptCanvasId.ToString().c_str()),
AZ::UserSettings::CT_LOCAL);
// Store a copy to revert if needed.
m_originalSettings = *settings;
ui->propertyEditor->setDisabled(false);
ui->propertyEditor->Setup(context, nullptr, false, 210);
ui->propertyEditor->AddInstance(settings.get(), settings->RTTI_GetType());
ui->propertyEditor->setObjectName("ui->propertyEditor");
ui->propertyEditor->SetSavedStateKey(AZ::Crc32(m_scriptCanvasId.ToString().c_str()));
ConfigurePropertyEditor(ui->propertyEditor);
}
else
{
ui->propertyEditor->setDisabled(true);
}
}
void SettingsDialog::RevertSettings()
{
if (m_settingsType == SettingsType::Graph || m_settingsType == SettingsType::All)
{
if (m_scriptCanvasId.IsValid())
{
AZStd::intrusive_ptr<Settings> settings =
AZ::UserSettings::CreateFind<Settings>(AZ::Crc32(m_scriptCanvasId.ToString().c_str()),
AZ::UserSettings::CT_LOCAL);
// Revert the stored copy, no changes will be stored.
*settings = m_originalSettings;
}
}
if (m_settingsType == SettingsType::General || m_settingsType == SettingsType::All)
{
// General properties
AZStd::intrusive_ptr<EditorSettings::ScriptCanvasEditorSettings> previewSettings =
AZ::UserSettings::CreateFind<EditorSettings::ScriptCanvasEditorSettings>(
AZ_CRC("ScriptCanvasPreviewSettings", 0x1c5a2965), AZ::UserSettings::CT_LOCAL);
*previewSettings = m_originalEditorSettings;
}
m_revertOnClose = false;
}
#include <Editor/View/Dialogs/moc_Settings.cpp>
}
@@ -0,0 +1,99 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QDialog>
#include <AzCore/std/smart_ptr/unique_ptr.h>
#include <AzCore/UserSettings/UserSettings.h>
#include <AzCore/Component/EntityId.h>
#include <Editor/Settings.h>
#include <ScriptCanvas/Core/Core.h>
#endif
namespace Ui
{
class SettingsDialog;
}
namespace AzToolsFramework
{
class ReflectedPropertyEditor;
}
namespace ScriptCanvasEditor
{
class Settings
: public AZ::UserSettings
{
public:
AZ_RTTI(Settings, "{E3B5DE71-FB4E-472C-BD2A-BD180E68B9A6}", AZ::UserSettings);
AZ_CLASS_ALLOCATOR(Settings, AZ::SystemAllocator, 0);
Settings()
: m_enableLogging(false)
{}
bool m_enableLogging;
static void Reflect(AZ::ReflectContext* reflection);
};
enum class SettingsType
{
None,
All,
General,
Graph
};
class SettingsDialog
: public QDialog
{
Q_OBJECT
public:
SettingsDialog(const QString& title, ScriptCanvas::ScriptCanvasId scriptCanvasId, QWidget* pParent = nullptr);
~SettingsDialog() override;
const QString& GetText() const { return m_text; }
protected:
void OnOK();
void OnCancel();
void OnTextChanged(const QString& text);
void ConfigurePropertyEditor(AzToolsFramework::ReflectedPropertyEditor*);
private:
void SetType(SettingsType settingsType);
void SetupGeneralSettings(AZ::SerializeContext* context);
void SetupGraphSettings(AZ::SerializeContext* context);
void RevertSettings();
QString m_text;
ScriptCanvas::ScriptCanvasId m_scriptCanvasId;
bool m_revertOnClose;
Settings m_originalSettings;
EditorSettings::ScriptCanvasEditorSettings m_originalEditorSettings;
SettingsType m_settingsType = SettingsType::None;
Ui::SettingsDialog* ui;
};
}
@@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsDialog</class>
<widget class="QDialog" name="SettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>500</width>
<height>400</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>500</width>
<height>400</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>500</width>
<height>400</height>
</size>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<widget class="QScrollArea" name="scrollArea">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>476</width>
<height>76</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QVBoxLayout" name="scrollAreaLayout">
<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="graphLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Graph Preferences</string>
</property>
</widget>
</item>
<item>
<widget class="AzToolsFramework::ReflectedPropertyEditor" name="propertyEditor" native="true">
</widget>
</item>
<item>
<widget class="QLabel" name="generalLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>General Preferences</string>
</property>
</widget>
</item>
<item>
<widget class="AzToolsFramework::ReflectedPropertyEditor" name="previewSettingsPropertyEditor" native="true">
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>6</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<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>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="ok">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>AzToolsFramework::ReflectedPropertyEditor</class>
<extends>QWidget</extends>
<header location="global">AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include "precompiled.h"
#include "UnsavedChangesDialog.h"
#include <QPushButton>
#include "Editor/View/Dialogs/ui_UnsavedChangesDialog.h"
namespace ScriptCanvasEditor
{
UnsavedChangesDialog::UnsavedChangesDialog(const QString& filename, QWidget* pParent /*=nullptr*/)
: QDialog(pParent)
, ui(new Ui::UnsavedChangesDialog)
{
ui->setupUi(this);
ui->m_saveLabel->setText(filename);
QObject::connect(ui->m_saveButton, &QPushButton::clicked, this, &UnsavedChangesDialog::OnSaveButton);
QObject::connect(ui->m_continueButton, &QPushButton::clicked, this, &UnsavedChangesDialog::OnContinueWithoutSavingButton);
QObject::connect(ui->m_cancelButton, &QPushButton::clicked, this, &UnsavedChangesDialog::OnCancelWithoutSavingButton);
}
void UnsavedChangesDialog::OnSaveButton(bool)
{
m_result = UnsavedChangesOptions::SAVE;
accept();
}
void UnsavedChangesDialog::OnContinueWithoutSavingButton(bool)
{
m_result = UnsavedChangesOptions::CONTINUE_WITHOUT_SAVING;
accept();
}
void UnsavedChangesDialog::OnCancelWithoutSavingButton([[maybe_unused]] bool clicked)
{
m_result = UnsavedChangesOptions::CANCEL_WITHOUT_SAVING;
accept();
}
#include <Editor/View/Dialogs/moc_UnsavedChangesDialog.cpp>
}
@@ -0,0 +1,54 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/Memory/SystemAllocator.h>
#include <QDialog>
#endif
namespace Ui
{
class UnsavedChangesDialog;
}
namespace ScriptCanvasEditor
{
enum class UnsavedChangesOptions
{
SAVE,
CONTINUE_WITHOUT_SAVING,
CANCEL_WITHOUT_SAVING,
INVALID
};
class UnsavedChangesDialog
: public QDialog
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(UnsavedChangesDialog, AZ::SystemAllocator, 0);
UnsavedChangesDialog(const QString& filename, QWidget* pParent = nullptr);
UnsavedChangesOptions GetResult() const { return m_result; }
protected:
void OnSaveButton(bool clicked);
void OnContinueWithoutSavingButton(bool clicked);
void OnCancelWithoutSavingButton(bool clicked);
Ui::UnsavedChangesDialog* ui;
UnsavedChangesOptions m_result = UnsavedChangesOptions::INVALID;
};
}
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UnsavedChangesDialog</class>
<widget class="QDialog" name="SaveChangesDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>404</width>
<height>75</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="m_saveLabel">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>391</width>
<height>41</height>
</rect>
</property>
<property name="text">
<string>Would you like to save changes?</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<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>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_saveButton">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_continueButton">
<property name="text">
<string>Don't Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_cancelButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
<property name="windowTitle">
<string>Save Script Canvas Changes?</string>
</property>
</widget>
<resources/>
<connections/>
</ui>