~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/samples/winrt/ImageManipulations/common/LayoutAwarePage.cpp

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//*********************************************************
 
2
//
 
3
// Copyright (c) Microsoft. All rights reserved.
 
4
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
 
5
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
 
6
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
 
7
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
 
8
//
 
9
//*********************************************************
 
10
 
 
11
#include "pch.h"
 
12
#include "LayoutAwarePage.h"
 
13
#include "SuspensionManager.h"
 
14
 
 
15
using namespace SDKSample::Common;
 
16
 
 
17
using namespace Platform;
 
18
using namespace Platform::Collections;
 
19
using namespace Windows::Foundation;
 
20
using namespace Windows::Foundation::Collections;
 
21
using namespace Windows::System;
 
22
using namespace Windows::UI::Core;
 
23
using namespace Windows::UI::ViewManagement;
 
24
using namespace Windows::UI::Xaml;
 
25
using namespace Windows::UI::Xaml::Controls;
 
26
using namespace Windows::UI::Xaml::Interop;
 
27
using namespace Windows::UI::Xaml::Navigation;
 
28
 
 
29
/// <summary>
 
30
/// Initializes a new instance of the <see cref="LayoutAwarePage"/> class.
 
31
/// </summary>
 
32
LayoutAwarePage::LayoutAwarePage()
 
33
{
 
34
    if (Windows::ApplicationModel::DesignMode::DesignModeEnabled)
 
35
    {
 
36
        return;
 
37
    }
 
38
 
 
39
    // Create an empty default view model
 
40
    DefaultViewModel = ref new Map<String^, Object^>(std::less<String^>());
 
41
 
 
42
    // When this page is part of the visual tree make two changes:
 
43
    // 1) Map application view state to visual state for the page
 
44
    // 2) Handle keyboard and mouse navigation requests
 
45
    Loaded += ref new RoutedEventHandler(this, &LayoutAwarePage::OnLoaded);
 
46
 
 
47
    // Undo the same changes when the page is no longer visible
 
48
    Unloaded += ref new RoutedEventHandler(this, &LayoutAwarePage::OnUnloaded);
 
49
}
 
50
 
 
51
static DependencyProperty^ _defaultViewModelProperty =
 
52
    DependencyProperty::Register("DefaultViewModel",
 
53
    TypeName(IObservableMap<String^, Object^>::typeid), TypeName(LayoutAwarePage::typeid), nullptr);
 
54
 
 
55
/// <summary>
 
56
/// Identifies the <see cref="DefaultViewModel"/> dependency property.
 
57
/// </summary>
 
58
DependencyProperty^ LayoutAwarePage::DefaultViewModelProperty::get()
 
59
{
 
60
    return _defaultViewModelProperty;
 
61
}
 
62
 
 
63
/// <summary>
 
64
/// Gets an implementation of <see cref="IObservableMap&lt;String, Object&gt;"/> designed to be
 
65
/// used as a trivial view model.
 
66
/// </summary>
 
67
IObservableMap<String^, Object^>^ LayoutAwarePage::DefaultViewModel::get()
 
68
{
 
69
    return safe_cast<IObservableMap<String^, Object^>^>(GetValue(DefaultViewModelProperty));
 
70
}
 
71
 
 
72
/// <summary>
 
73
/// Sets an implementation of <see cref="IObservableMap&lt;String, Object&gt;"/> designed to be
 
74
/// used as a trivial view model.
 
75
/// </summary>
 
76
void LayoutAwarePage::DefaultViewModel::set(IObservableMap<String^, Object^>^ value)
 
77
{
 
78
    SetValue(DefaultViewModelProperty, value);
 
79
}
 
80
 
 
81
/// <summary>
 
82
/// Invoked when the page is part of the visual tree
 
83
/// </summary>
 
84
/// <param name="sender">Instance that triggered the event.</param>
 
85
/// <param name="e">Event data describing the conditions that led to the event.</param>
 
86
void LayoutAwarePage::OnLoaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 
87
{
 
88
    this->StartLayoutUpdates(sender, e);
 
89
 
 
90
    // Keyboard and mouse navigation only apply when occupying the entire window
 
91
    if (this->ActualHeight == Window::Current->Bounds.Height &&
 
92
        this->ActualWidth == Window::Current->Bounds.Width)
 
93
    {
 
94
        // Listen to the window directly so focus isn't required
 
95
        _acceleratorKeyEventToken = Window::Current->CoreWindow->Dispatcher->AcceleratorKeyActivated +=
 
96
            ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(this,
 
97
            &LayoutAwarePage::CoreDispatcher_AcceleratorKeyActivated);
 
98
        _pointerPressedEventToken = Window::Current->CoreWindow->PointerPressed +=
 
99
            ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this,
 
100
            &LayoutAwarePage::CoreWindow_PointerPressed);
 
101
        _navigationShortcutsRegistered = true;
 
102
    }
 
103
}
 
104
 
 
105
/// <summary>
 
106
/// Invoked when the page is removed from visual tree
 
107
/// </summary>
 
108
/// <param name="sender">Instance that triggered the event.</param>
 
109
/// <param name="e">Event data describing the conditions that led to the event.</param>
 
110
void LayoutAwarePage::OnUnloaded(Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
 
111
{
 
112
    if (_navigationShortcutsRegistered)
 
113
    {
 
114
        Window::Current->CoreWindow->Dispatcher->AcceleratorKeyActivated -= _acceleratorKeyEventToken;
 
115
        Window::Current->CoreWindow->PointerPressed -= _pointerPressedEventToken;
 
116
        _navigationShortcutsRegistered = false;
 
117
    }
 
118
    StopLayoutUpdates(sender, e);
 
119
}
 
120
 
 
121
#pragma region Navigation support
 
122
 
 
123
/// <summary>
 
124
/// Invoked as an event handler to navigate backward in the page's associated <see cref="Frame"/>
 
125
/// until it reaches the top of the navigation stack.
 
126
/// </summary>
 
127
/// <param name="sender">Instance that triggered the event.</param>
 
128
/// <param name="e">Event data describing the conditions that led to the event.</param>
 
129
void LayoutAwarePage::GoHome(Object^ sender, RoutedEventArgs^ e)
 
130
{
 
131
    (void) sender;      // Unused parameter
 
132
    (void) e;   // Unused parameter
 
133
 
 
134
    // Use the navigation frame to return to the topmost page
 
135
    if (Frame != nullptr)
 
136
    {
 
137
        while (Frame->CanGoBack)
 
138
        {
 
139
            Frame->GoBack();
 
140
        }
 
141
    }
 
142
}
 
143
 
 
144
/// <summary>
 
145
/// Invoked as an event handler to navigate backward in the navigation stack
 
146
/// associated with this page's <see cref="Frame"/>.
 
147
/// </summary>
 
148
/// <param name="sender">Instance that triggered the event.</param>
 
149
/// <param name="e">Event data describing the conditions that led to the event.</param>
 
150
void LayoutAwarePage::GoBack(Object^ sender, RoutedEventArgs^ e)
 
151
{
 
152
    (void) sender;      // Unused parameter
 
153
    (void) e;   // Unused parameter
 
154
 
 
155
    // Use the navigation frame to return to the previous page
 
156
    if (Frame != nullptr && Frame->CanGoBack)
 
157
    {
 
158
        Frame->GoBack();
 
159
    }
 
160
}
 
161
 
 
162
/// <summary>
 
163
/// Invoked as an event handler to navigate forward in the navigation stack
 
164
/// associated with this page's <see cref="Frame"/>.
 
165
/// </summary>
 
166
/// <param name="sender">Instance that triggered the event.</param>
 
167
/// <param name="e">Event data describing the conditions that led to the event.</param>
 
168
void LayoutAwarePage::GoForward(Object^ sender, RoutedEventArgs^ e)
 
169
{
 
170
    (void) sender;      // Unused parameter
 
171
    (void) e;   // Unused parameter
 
172
 
 
173
    // Use the navigation frame to advance to the next page
 
174
    if (Frame != nullptr && Frame->CanGoForward)
 
175
    {
 
176
        Frame->GoForward();
 
177
    }
 
178
}
 
179
 
 
180
/// <summary>
 
181
/// Invoked on every keystroke, including system keys such as Alt key combinations, when
 
182
/// this page is active and occupies the entire window.  Used to detect keyboard navigation
 
183
/// between pages even when the page itself doesn't have focus.
 
184
/// </summary>
 
185
/// <param name="sender">Instance that triggered the event.</param>
 
186
/// <param name="args">Event data describing the conditions that led to the event.</param>
 
187
void LayoutAwarePage::CoreDispatcher_AcceleratorKeyActivated(CoreDispatcher^ sender, AcceleratorKeyEventArgs^ args)
 
188
{
 
189
    auto virtualKey = args->VirtualKey;
 
190
 
 
191
    // Only investigate further when Left, Right, or the dedicated Previous or Next keys
 
192
    // are pressed
 
193
    if ((args->EventType == CoreAcceleratorKeyEventType::SystemKeyDown ||
 
194
        args->EventType == CoreAcceleratorKeyEventType::KeyDown) &&
 
195
        (virtualKey == VirtualKey::Left || virtualKey == VirtualKey::Right ||
 
196
        (int)virtualKey == 166 || (int)virtualKey == 167))
 
197
    {
 
198
        auto coreWindow = Window::Current->CoreWindow;
 
199
        auto downState = Windows::UI::Core::CoreVirtualKeyStates::Down;
 
200
        bool menuKey = (coreWindow->GetKeyState(VirtualKey::Menu) & downState) == downState;
 
201
        bool controlKey = (coreWindow->GetKeyState(VirtualKey::Control) & downState) == downState;
 
202
        bool shiftKey = (coreWindow->GetKeyState(VirtualKey::Shift) & downState) == downState;
 
203
        bool noModifiers = !menuKey && !controlKey && !shiftKey;
 
204
        bool onlyAlt = menuKey && !controlKey && !shiftKey;
 
205
 
 
206
        if (((int)virtualKey == 166 && noModifiers) ||
 
207
            (virtualKey == VirtualKey::Left && onlyAlt))
 
208
        {
 
209
            // When the previous key or Alt+Left are pressed navigate back
 
210
            args->Handled = true;
 
211
            GoBack(this, ref new RoutedEventArgs());
 
212
        }
 
213
        else if (((int)virtualKey == 167 && noModifiers) ||
 
214
            (virtualKey == VirtualKey::Right && onlyAlt))
 
215
        {
 
216
            // When the next key or Alt+Right are pressed navigate forward
 
217
            args->Handled = true;
 
218
            GoForward(this, ref new RoutedEventArgs());
 
219
        }
 
220
    }
 
221
}
 
222
 
 
223
/// <summary>
 
224
/// Invoked on every mouse click, touch screen tap, or equivalent interaction when this
 
225
/// page is active and occupies the entire window.  Used to detect browser-style next and
 
226
/// previous mouse button clicks to navigate between pages.
 
227
/// </summary>
 
228
/// <param name="sender">Instance that triggered the event.</param>
 
229
/// <param name="args">Event data describing the conditions that led to the event.</param>
 
230
void LayoutAwarePage::CoreWindow_PointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
 
231
{
 
232
    auto properties = args->CurrentPoint->Properties;
 
233
 
 
234
    // Ignore button chords with the left, right, and middle buttons
 
235
    if (properties->IsLeftButtonPressed || properties->IsRightButtonPressed ||
 
236
        properties->IsMiddleButtonPressed) return;
 
237
 
 
238
    // If back or forward are pressed (but not both) navigate appropriately
 
239
    bool backPressed = properties->IsXButton1Pressed;
 
240
    bool forwardPressed = properties->IsXButton2Pressed;
 
241
    if (backPressed ^ forwardPressed)
 
242
    {
 
243
        args->Handled = true;
 
244
        if (backPressed) GoBack(this, ref new RoutedEventArgs());
 
245
        if (forwardPressed) GoForward(this, ref new RoutedEventArgs());
 
246
    }
 
247
}
 
248
 
 
249
#pragma endregion
 
250
 
 
251
#pragma region Visual state switching
 
252
 
 
253
/// <summary>
 
254
/// Invoked as an event handler, typically on the <see cref="Loaded"/> event of a
 
255
/// <see cref="Control"/> within the page, to indicate that the sender should start receiving
 
256
/// visual state management changes that correspond to application view state changes.
 
257
/// </summary>
 
258
/// <param name="sender">Instance of <see cref="Control"/> that supports visual state management
 
259
/// corresponding to view states.</param>
 
260
/// <param name="e">Event data that describes how the request was made.</param>
 
261
/// <remarks>The current view state will immediately be used to set the corresponding visual state
 
262
/// when layout updates are requested.  A corresponding <see cref="Unloaded"/> event handler
 
263
/// connected to <see cref="StopLayoutUpdates"/> is strongly encouraged.  Instances of
 
264
/// <see cref="LayoutAwarePage"/> automatically invoke these handlers in their Loaded and Unloaded
 
265
/// events.</remarks>
 
266
/// <seealso cref="DetermineVisualState"/>
 
267
/// <seealso cref="InvalidateVisualState"/>
 
268
void LayoutAwarePage::StartLayoutUpdates(Object^ sender, RoutedEventArgs^ e)
 
269
{
 
270
    (void) e;   // Unused parameter
 
271
 
 
272
    auto control = safe_cast<Control^>(sender);
 
273
    if (_layoutAwareControls == nullptr)
 
274
    {
 
275
        // Start listening to view state changes when there are controls interested in updates
 
276
        _layoutAwareControls = ref new Vector<Control^>();
 
277
        _windowSizeEventToken = Window::Current->SizeChanged += ref new WindowSizeChangedEventHandler(this, &LayoutAwarePage::WindowSizeChanged);
 
278
 
 
279
        // Page receives notifications for children. Protect the page until we stopped layout updates for all controls.
 
280
        _this = this;
 
281
    }
 
282
    _layoutAwareControls->Append(control);
 
283
 
 
284
    // Set the initial visual state of the control
 
285
    VisualStateManager::GoToState(control, DetermineVisualState(ApplicationView::Value), false);
 
286
}
 
287
 
 
288
void LayoutAwarePage::WindowSizeChanged(Object^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ e)
 
289
{
 
290
    (void) sender;      // Unused parameter
 
291
    (void) e;   // Unused parameter
 
292
 
 
293
    InvalidateVisualState();
 
294
}
 
295
 
 
296
/// <summary>
 
297
/// Invoked as an event handler, typically on the <see cref="Unloaded"/> event of a
 
298
/// <see cref="Control"/>, to indicate that the sender should start receiving visual state
 
299
/// management changes that correspond to application view state changes.
 
300
/// </summary>
 
301
/// <param name="sender">Instance of <see cref="Control"/> that supports visual state management
 
302
/// corresponding to view states.</param>
 
303
/// <param name="e">Event data that describes how the request was made.</param>
 
304
/// <remarks>The current view state will immediately be used to set the corresponding visual state
 
305
/// when layout updates are requested.</remarks>
 
306
/// <seealso cref="StartLayoutUpdates"/>
 
307
void LayoutAwarePage::StopLayoutUpdates(Object^ sender, RoutedEventArgs^ e)
 
308
{
 
309
    (void) e;   // Unused parameter
 
310
 
 
311
    auto control = safe_cast<Control^>(sender);
 
312
    unsigned int index;
 
313
    if (_layoutAwareControls != nullptr && _layoutAwareControls->IndexOf(control, &index))
 
314
    {
 
315
        _layoutAwareControls->RemoveAt(index);
 
316
        if (_layoutAwareControls->Size == 0)
 
317
        {
 
318
            // Stop listening to view state changes when no controls are interested in updates
 
319
            Window::Current->SizeChanged -= _windowSizeEventToken;
 
320
            _layoutAwareControls = nullptr;
 
321
            // Last control has received the Unload notification.
 
322
            _this = nullptr;
 
323
        }
 
324
    }
 
325
}
 
326
 
 
327
/// <summary>
 
328
/// Translates <see cref="ApplicationViewState"/> values into strings for visual state management
 
329
/// within the page.  The default implementation uses the names of enum values.  Subclasses may
 
330
/// override this method to control the mapping scheme used.
 
331
/// </summary>
 
332
/// <param name="viewState">View state for which a visual state is desired.</param>
 
333
/// <returns>Visual state name used to drive the <see cref="VisualStateManager"/></returns>
 
334
/// <seealso cref="InvalidateVisualState"/>
 
335
String^ LayoutAwarePage::DetermineVisualState(ApplicationViewState viewState)
 
336
{
 
337
    switch (viewState)
 
338
    {
 
339
    case ApplicationViewState::Filled:
 
340
        return "Filled";
 
341
    case ApplicationViewState::Snapped:
 
342
        return "Snapped";
 
343
    case ApplicationViewState::FullScreenPortrait:
 
344
        return "FullScreenPortrait";
 
345
    case ApplicationViewState::FullScreenLandscape:
 
346
    default:
 
347
        return "FullScreenLandscape";
 
348
    }
 
349
}
 
350
 
 
351
/// <summary>
 
352
/// Updates all controls that are listening for visual state changes with the correct visual
 
353
/// state.
 
354
/// </summary>
 
355
/// <remarks>
 
356
/// Typically used in conjunction with overriding <see cref="DetermineVisualState"/> to
 
357
/// signal that a different value may be returned even though the view state has not changed.
 
358
/// </remarks>
 
359
void LayoutAwarePage::InvalidateVisualState()
 
360
{
 
361
    if (_layoutAwareControls != nullptr)
 
362
    {
 
363
        String^ visualState = DetermineVisualState(ApplicationView::Value);
 
364
        auto controlIterator = _layoutAwareControls->First();
 
365
        while (controlIterator->HasCurrent)
 
366
        {
 
367
            auto control = controlIterator->Current;
 
368
            VisualStateManager::GoToState(control, visualState, false);
 
369
            controlIterator->MoveNext();
 
370
        }
 
371
    }
 
372
}
 
373
 
 
374
#pragma endregion
 
375
 
 
376
#pragma region Process lifetime management
 
377
 
 
378
/// <summary>
 
379
/// Invoked when this page is about to be displayed in a Frame.
 
380
/// </summary>
 
381
/// <param name="e">Event data that describes how this page was reached.  The Parameter
 
382
/// property provides the group to be displayed.</param>
 
383
void LayoutAwarePage::OnNavigatedTo(NavigationEventArgs^ e)
 
384
{
 
385
    // Returning to a cached page through navigation shouldn't trigger state loading
 
386
    if (_pageKey != nullptr) return;
 
387
 
 
388
    auto frameState = SuspensionManager::SessionStateForFrame(Frame);
 
389
    _pageKey = "Page-" + Frame->BackStackDepth;
 
390
 
 
391
    if (e->NavigationMode == NavigationMode::New)
 
392
    {
 
393
        // Clear existing state for forward navigation when adding a new page to the
 
394
        // navigation stack
 
395
        auto nextPageKey = _pageKey;
 
396
        int nextPageIndex = Frame->BackStackDepth;
 
397
        while (frameState->HasKey(nextPageKey))
 
398
        {
 
399
            frameState->Remove(nextPageKey);
 
400
            nextPageIndex++;
 
401
            nextPageKey = "Page-" + nextPageIndex;
 
402
        }
 
403
 
 
404
        // Pass the navigation parameter to the new page
 
405
        LoadState(e->Parameter, nullptr);
 
406
    }
 
407
    else
 
408
    {
 
409
        // Pass the navigation parameter and preserved page state to the page, using
 
410
        // the same strategy for loading suspended state and recreating pages discarded
 
411
        // from cache
 
412
        LoadState(e->Parameter, safe_cast<IMap<String^, Object^>^>(frameState->Lookup(_pageKey)));
 
413
    }
 
414
}
 
415
 
 
416
/// <summary>
 
417
/// Invoked when this page will no longer be displayed in a Frame.
 
418
/// </summary>
 
419
/// <param name="e">Event data that describes how this page was reached.  The Parameter
 
420
/// property provides the group to be displayed.</param>
 
421
void LayoutAwarePage::OnNavigatedFrom(NavigationEventArgs^ e)
 
422
{
 
423
    auto frameState = SuspensionManager::SessionStateForFrame(Frame);
 
424
    auto pageState = ref new Map<String^, Object^>();
 
425
    SaveState(pageState);
 
426
    frameState->Insert(_pageKey, pageState);
 
427
}
 
428
 
 
429
/// <summary>
 
430
/// Populates the page with content passed during navigation.  Any saved state is also
 
431
/// provided when recreating a page from a prior session.
 
432
/// </summary>
 
433
/// <param name="navigationParameter">The parameter value passed to
 
434
/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
 
435
/// </param>
 
436
/// <param name="pageState">A map of state preserved by this page during an earlier
 
437
/// session.  This will be null the first time a page is visited.</param>
 
438
void LayoutAwarePage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)
 
439
{
 
440
}
 
441
 
 
442
/// <summary>
 
443
/// Preserves state associated with this page in case the application is suspended or the
 
444
/// page is discarded from the navigation cache.  Values must conform to the serialization
 
445
/// requirements of <see cref="SuspensionManager.SessionState"/>.
 
446
/// </summary>
 
447
/// <param name="pageState">An empty map to be populated with serializable state.</param>
 
448
void LayoutAwarePage::SaveState(IMap<String^, Object^>^ pageState)
 
449
{
 
450
}
 
451
 
 
452
#pragma endregion