Home | History | Annotate | Download | only in ImageManipulations
      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 //
     12 // MainPage.xaml.cpp
     13 // Implementation of the MainPage.xaml class.
     14 //
     15 
     16 #include "pch.h"
     17 #include "MainPage.xaml.h"
     18 #include "App.xaml.h"
     19 
     20 #include <collection.h>
     21 
     22 using namespace Windows::UI::Xaml;
     23 using namespace Windows::UI::Xaml::Controls;
     24 using namespace Windows::Foundation;
     25 using namespace Windows::Foundation::Collections;
     26 using namespace Platform;
     27 using namespace SDKSample;
     28 using namespace Windows::UI::Xaml::Navigation;
     29 using namespace Windows::UI::Xaml::Interop;
     30 using namespace Windows::Graphics::Display;
     31 using namespace Windows::UI::ViewManagement;
     32 
     33 MainPage^ MainPage::Current = nullptr;
     34 
     35 MainPage::MainPage()
     36 {
     37     InitializeComponent();
     38 
     39     // This frame is hidden, meaning it is never shown.  It is simply used to load
     40     // each scenario page and then pluck out the input and output sections and
     41     // place them into the UserControls on the main page.
     42     HiddenFrame = ref new Windows::UI::Xaml::Controls::Frame();
     43     HiddenFrame->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
     44     ContentRoot->Children->Append(HiddenFrame);
     45 
     46     FeatureName->Text = FEATURE_NAME;
     47 
     48     this->SizeChanged += ref new SizeChangedEventHandler(this, &MainPage::MainPage_SizeChanged);
     49     Scenarios->SelectionChanged += ref new SelectionChangedEventHandler(this, &MainPage::Scenarios_SelectionChanged);
     50 
     51     MainPage::Current = this;
     52     autoSizeInputSectionWhenSnapped = true;
     53 }
     54 
     55 /// <summary>
     56 /// We need to handle SizeChanged so that we can make the sample layout property
     57 /// in the various layouts.
     58 /// </summary>
     59 /// <param name="sender"></param>
     60 /// <param name="e"></param>
     61 void MainPage::MainPage_SizeChanged(Object^ sender, SizeChangedEventArgs^ e)
     62 {
     63     InvalidateSize();
     64     MainPageSizeChangedEventArgs^ args = ref new MainPageSizeChangedEventArgs();
     65     args->ViewState = ApplicationView::Value;
     66     MainPageResized(this, args);
     67 
     68 }
     69 
     70 void MainPage::InvalidateSize()
     71 {
     72     // Get the window width
     73     double windowWidth = this->ActualWidth;
     74 
     75     if (windowWidth != 0.0)
     76     {
     77         // Get the width of the ListBox.
     78         double listBoxWidth = Scenarios->ActualWidth;
     79 
     80         // Is the ListBox using any margins that we need to consider?
     81         double listBoxMarginLeft = Scenarios->Margin.Left;
     82         double listBoxMarginRight = Scenarios->Margin.Right;
     83 
     84         // Figure out how much room is left after considering the list box width
     85         double availableWidth = windowWidth - listBoxWidth;
     86 
     87         // Is the top most child using margins?
     88         double layoutRootMarginLeft = ContentRoot->Margin.Left;
     89         double layoutRootMarginRight = ContentRoot->Margin.Right;
     90 
     91         // We have different widths to use depending on the view state
     92         if (ApplicationView::Value != ApplicationViewState::Snapped)
     93         {
     94             // Make us as big as the the left over space, factoring in the ListBox width, the ListBox margins.
     95             // and the LayoutRoot's margins
     96             InputSection->Width = ((availableWidth) -
     97                 (layoutRootMarginLeft + layoutRootMarginRight + listBoxMarginLeft + listBoxMarginRight));
     98         }
     99         else
    100         {
    101             // Make us as big as the left over space, factoring in just the LayoutRoot's margins.
    102             if (autoSizeInputSectionWhenSnapped)
    103             {
    104                 InputSection->Width = (windowWidth - (layoutRootMarginLeft + layoutRootMarginRight));
    105             }
    106         }
    107     }
    108     InvalidateViewState();
    109 }
    110 
    111 void MainPage::InvalidateViewState()
    112 {
    113     // Are we going to snapped mode?
    114     if (ApplicationView::Value == ApplicationViewState::Snapped)
    115     {
    116         Grid::SetRow(DescriptionText, 3);
    117         Grid::SetColumn(DescriptionText, 0);
    118 
    119         Grid::SetRow(InputSection, 4);
    120         Grid::SetColumn(InputSection, 0);
    121 
    122         Grid::SetRow(FooterPanel, 2);
    123         Grid::SetColumn(FooterPanel, 0);
    124     }
    125     else
    126     {
    127         Grid::SetRow(DescriptionText, 1);
    128         Grid::SetColumn(DescriptionText, 1);
    129 
    130         Grid::SetRow(InputSection, 2);
    131         Grid::SetColumn(InputSection, 1);
    132 
    133         Grid::SetRow(FooterPanel, 1);
    134         Grid::SetColumn(FooterPanel, 1);
    135     }
    136 
    137     //  Since we don't load the scenario page in the traditional manner (we just pluck out the
    138     // input and output sections from the page) we need to ensure that any VSM code used
    139     // by the scenario's input and output sections is fired.
    140     VisualStateManager::GoToState(InputSection, "Input" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);
    141     VisualStateManager::GoToState(OutputSection, "Output" + LayoutAwarePage::DetermineVisualState(ApplicationView::Value), false);
    142 }
    143 
    144 void MainPage::PopulateScenarios()
    145 {
    146     ScenarioList = ref new Platform::Collections::Vector<Object^>();
    147 
    148     // Populate the ListBox with the list of scenarios as defined in Constants.cpp.
    149     for (unsigned int i = 0; i < scenarios->Length; ++i)
    150     {
    151         Scenario s = scenarios[i];
    152         ListBoxItem^ item = ref new ListBoxItem();
    153         item->Name = s.ClassName;
    154         item->Content = (i + 1).ToString() + ") " + s.Title;
    155         ScenarioList->Append(item);
    156     }
    157 
    158     // Bind the ListBox to the scenario list.
    159     Scenarios->ItemsSource = ScenarioList;
    160     Scenarios->ScrollIntoView(Scenarios->SelectedItem);
    161 }
    162 
    163 /// <summary>
    164 /// This method is responsible for loading the individual input and output sections for each scenario.  This
    165 /// is based on navigating a hidden Frame to the ScenarioX.xaml page and then extracting out the input
    166 /// and output sections into the respective UserControl on the main page.
    167 /// </summary>
    168 /// <param name="scenarioName"></param>
    169 void MainPage::LoadScenario(String^ scenarioName)
    170 {
    171     autoSizeInputSectionWhenSnapped = true;
    172 
    173     // Load the ScenarioX.xaml file into the Frame.
    174     TypeName scenarioType = {scenarioName, TypeKind::Custom};
    175     HiddenFrame->Navigate(scenarioType, this);
    176 
    177     // Get the top element, the Page, so we can look up the elements
    178     // that represent the input and output sections of the ScenarioX file.
    179     Page^ hiddenPage = safe_cast<Page^>(HiddenFrame->Content);
    180 
    181     // Get each element.
    182     UIElement^ input = safe_cast<UIElement^>(hiddenPage->FindName("Input"));
    183     UIElement^ output = safe_cast<UIElement^>(hiddenPage->FindName("Output"));
    184 
    185     if (input == nullptr)
    186     {
    187         // Malformed input section.
    188         NotifyUser("Cannot load scenario input section for " + scenarioName +
    189             "  Make sure root of input section markup has x:Name of 'Input'", NotifyType::ErrorMessage);
    190         return;
    191     }
    192 
    193     if (output == nullptr)
    194     {
    195         // Malformed output section.
    196         NotifyUser("Cannot load scenario output section for " + scenarioName +
    197             "  Make sure root of output section markup has x:Name of 'Output'", NotifyType::ErrorMessage);
    198         return;
    199     }
    200 
    201     // Find the LayoutRoot which parents the input and output sections in the main page.
    202     Panel^ panel = safe_cast<Panel^>(hiddenPage->FindName("LayoutRoot"));
    203 
    204     if (panel != nullptr)
    205     {
    206         unsigned int index = 0;
    207         UIElementCollection^ collection = panel->Children;
    208 
    209         // Get rid of the content that is currently in the intput and output sections.
    210         collection->IndexOf(input, &index);
    211         collection->RemoveAt(index);
    212 
    213         collection->IndexOf(output, &index);
    214         collection->RemoveAt(index);
    215 
    216         // Populate the input and output sections with the newly loaded content.
    217         InputSection->Content = input;
    218         OutputSection->Content = output;
    219 
    220         ScenarioLoaded(this, nullptr);
    221     }
    222     else
    223     {
    224         // Malformed Scenario file.
    225         NotifyUser("Cannot load scenario: " + scenarioName + ".  Make sure root tag in the '" +
    226             scenarioName + "' file has an x:Name of 'LayoutRoot'", NotifyType::ErrorMessage);
    227     }
    228 }
    229 
    230 void MainPage::Scenarios_SelectionChanged(Object^ sender, SelectionChangedEventArgs^ e)
    231 {
    232     if (Scenarios->SelectedItem != nullptr)
    233     {
    234         NotifyUser("", NotifyType::StatusMessage);
    235 
    236         LoadScenario((safe_cast<ListBoxItem^>(Scenarios->SelectedItem))->Name);
    237         InvalidateSize();
    238     }
    239 }
    240 
    241 void MainPage::NotifyUser(String^ strMessage, NotifyType type)
    242 {
    243     switch (type)
    244     {
    245     case NotifyType::StatusMessage:
    246         // Use the status message style.
    247         StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("StatusStyle"));
    248         break;
    249     case NotifyType::ErrorMessage:
    250         // Use the error message style.
    251         StatusBlock->Style = safe_cast<Windows::UI::Xaml::Style^>(this->Resources->Lookup("ErrorStyle"));
    252         break;
    253     default:
    254         break;
    255     }
    256     StatusBlock->Text = strMessage;
    257 
    258     // Collapsed the StatusBlock if it has no text to conserve real estate.
    259     if (StatusBlock->Text != "")
    260     {
    261         StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Visible;
    262     }
    263     else
    264     {
    265         StatusBlock->Visibility = Windows::UI::Xaml::Visibility::Collapsed;
    266     }
    267 }
    268 
    269 void MainPage::Footer_Click(Object^ sender, RoutedEventArgs^ e)
    270 {
    271     auto uri = ref new Uri((String^)((HyperlinkButton^)sender)->Tag);
    272     Windows::System::Launcher::LaunchUriAsync(uri);
    273 }
    274 
    275 
    276 /// <summary>
    277 /// Populates the page with content passed during navigation.  Any saved state is also
    278 /// provided when recreating a page from a prior session.
    279 /// </summary>
    280 /// <param name="navigationParameter">The parameter value passed to
    281 /// <see cref="Frame::Navigate(Type, Object)"/> when this page was initially requested.
    282 /// </param>
    283 /// <param name="pageState">A map of state preserved by this page during an earlier
    284 /// session.  This will be null the first time a page is visited.</param>
    285 void MainPage::LoadState(Object^ navigationParameter, IMap<String^, Object^>^ pageState)
    286 {
    287     (void) navigationParameter;    // Unused parameter
    288 
    289     PopulateScenarios();
    290 
    291     // Starting scenario is the first or based upon a previous state.
    292     ListBoxItem^ startingScenario = nullptr;
    293     int startingScenarioIndex = -1;
    294 
    295     if (pageState != nullptr && pageState->HasKey("SelectedScenarioIndex"))
    296     {
    297         startingScenarioIndex = safe_cast<int>(pageState->Lookup("SelectedScenarioIndex"));
    298     }
    299 
    300     Scenarios->SelectedIndex = startingScenarioIndex != -1 ? startingScenarioIndex : 0;
    301 
    302     InvalidateViewState();
    303 }
    304 
    305 /// <summary>
    306 /// Preserves state associated with this page in case the application is suspended or the
    307 /// page is discarded from the navigation cache.  Values must conform to the serialization
    308 /// requirements of <see cref="SuspensionManager::SessionState"/>.
    309 /// </summary>
    310 /// <param name="pageState">An empty map to be populated with serializable state.</param>
    311 void MainPage::SaveState(IMap<String^, Object^>^ pageState)
    312 {
    313     int selectedListBoxItemIndex = Scenarios->SelectedIndex;
    314     pageState->Insert("SelectedScenarioIndex", selectedListBoxItemIndex);
    315 }
    316