calculator/src/Calculator/WindowFrameService.cpp
Matt Cooley 4cadfb204d
Remove unused PLM code (#7)
Remove LayoutAwarePage, SuspensionManager, and other suspend-resume handling code. SuspensionManager::SaveAsync and related methods weren't actually called anywhere. I didn't attempt to remove the serialize/deserialize code at the ViewModel layer, although much of that is likely not needed either.

We may decide we want to persist more state through a suspend-terminate-resume cycle (as the app might have done a long time ago). But if we decide we want that, we should not use a persistence mechanism that's closely coupled to frame navigation.
2019-02-01 15:15:48 -08:00

192 lines
6.2 KiB
C++

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#include "pch.h"
#include "WindowFrameService.h"
#include "CalcViewModel\Common\KeyboardShortcutManager.h"
using namespace concurrency;
using namespace Platform;
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
using namespace std;
using namespace Windows::ApplicationModel;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::Storage;
using namespace Windows::UI::Core;
using namespace Windows::UI::ViewManagement;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Interop;
using namespace Windows::UI::Xaml::Navigation;
namespace CalculatorApp
{
WindowFrameService^ WindowFrameService::CreateNewWindowFrameService(_In_ Frame^ viewFrame, bool createdByUs, Platform::WeakReference parent)
{
assert(CoreWindow::GetForCurrentThread() != nullptr);
auto frameService = ref new WindowFrameService(viewFrame, parent);
frameService->InitializeFrameService(createdByUs);
return frameService;
}
WindowFrameService::WindowFrameService(_In_ Frame^ frame, WeakReference parent)
: m_currentWindow(CoreWindow::GetForCurrentThread())
, m_coreDispatcher(m_currentWindow->Dispatcher)
, m_frame(frame)
, m_parent(parent)
, m_viewId(ApplicationView::GetApplicationViewIdForWindow(m_currentWindow.Get()))
{
}
void WindowFrameService::InitializeFrameService(bool createdByUs)
{
assert(createdByUs == (!CoreApplication::GetCurrentView()->IsHosted && !CoreApplication::GetCurrentView()->IsMain));
if (createdByUs)
{
ApplicationView::GetForCurrentView()->Consolidated +=
ref new TypedEventHandler<ApplicationView ^, ApplicationViewConsolidatedEventArgs ^>(this, &WindowFrameService::OnConsolidated);
}
else
{
CoreWindow::GetForCurrentThread()->Closed += ref new TypedEventHandler<CoreWindow ^, CoreWindowEventArgs ^>(this, &WindowFrameService::OnClosed);
}
}
CoreDispatcher^ WindowFrameService::GetCoreDispatcher()
{
return m_coreDispatcher.Get();
}
int WindowFrameService::GetViewId()
{
return m_viewId;
}
Frame^ WindowFrameService::GetFrame()
{
return m_frame;
}
Page^ WindowFrameService::GetCurrentPage()
{
return dynamic_cast<Page^>(m_frame->Content);
}
void WindowFrameService::SetNewFrame(_In_ Windows::UI::Xaml::Controls::Frame^ frame)
{
assert(frame->BackStackDepth == 0);
m_frame = frame;
}
void WindowFrameService::RegisterOnWindowClosingHandler(function<void()> onWindowClosingHandler)
{
m_onWindowClosingHandlers.push_back(onWindowClosingHandler);
}
void WindowFrameService::InvokeWindowClosingHandlers()
{
// Should be called only once just before we kill the window.
for (auto& handler : m_onWindowClosingHandlers)
{
handler();
}
m_onWindowClosingHandlers.clear();
}
task<void> WindowFrameService::HandleViewRelease()
{
auto that(this);
task_completion_event<void> closingHandlersCompletedEvent;
m_coreDispatcher->RunAsync(CoreDispatcherPriority::Low, ref new DispatchedHandler([that, closingHandlersCompletedEvent]()
{
KeyboardShortcutManager::OnWindowClosed(that->m_viewId);
Window::Current->Content = nullptr;
that->InvokeWindowClosingHandlers();
// This is to ensure InvokeWindowClosingHandlers is be done before RemoveWindowFromMap
// If InvokeWindowClosingHandlers throws any exception we want it to crash the application
// so we are ok not setting closingHandlersCompletedEvent in that case
closingHandlersCompletedEvent.set();
that->m_coreDispatcher->StopProcessEvents();
Window::Current->Close();
}));
return create_task(closingHandlersCompletedEvent);
}
void WindowFrameService::OnConsolidated(_In_ ApplicationView^ sender, _In_ ApplicationViewConsolidatedEventArgs^ e)
{
LogOnViewClosed(CoreWindow::GetForCurrentThread());
auto parent = m_parent.Resolve<App>();
if (parent != nullptr)
{
parent->RemoveWindow(this);
}
}
void WindowFrameService::OnClosed(_In_ CoreWindow^ sender, _In_ CoreWindowEventArgs^ args)
{
LogOnViewClosed(sender);
auto parent = m_parent.Resolve<App>();
if (parent != nullptr)
{
parent->RemoveSecondaryWindow(this);
}
}
void WindowFrameService::LogOnViewClosed(_In_ CoreWindow^ coreWindow)
{
if (coreWindow)
{
TraceLogger::GetInstance().LogViewClosingTelemetry(ApplicationView::GetApplicationViewIdForWindow(coreWindow));
}
else
{
TraceLogger::GetInstance().LogCoreWindowWasNull();
}
}
void WindowFrameService::RegisterRuntimeWindowService(TypeName serviceId, _In_opt_ Object^ service)
{
if (TryResolveRuntimeWindowService(serviceId))
{
throw ref new InvalidArgumentException(serviceId + L" already registered");
}
m_runtimeServicesMap[serviceId.Name] = service;
}
bool WindowFrameService::RemoveRuntimeWindowService(TypeName serviceId)
{
return m_runtimeServicesMap.erase(serviceId.Name) > 0;
}
Object^ WindowFrameService::ResolveRuntimeWindowService(TypeName serviceId)
{
auto service = TryResolveRuntimeWindowService(serviceId);
if (service)
{
return service;
}
else
{
throw ref new InvalidArgumentException(serviceId.Name + L" not found");
}
}
_Ret_maybenull_ Object^ WindowFrameService::TryResolveRuntimeWindowService(TypeName serviceId)
{
auto entry = m_runtimeServicesMap.find(serviceId.Name);
if (entry != m_runtimeServicesMap.end())
{
return entry->second;
}
return nullptr;
}
}