From 25608ed8730afe9fd34301c4a91091a653468938 Mon Sep 17 00:00:00 2001
From: atraczyk <andreastraczyk@gmail.com>
Date: Thu, 15 Sep 2016 11:12:16 -0400
Subject: [PATCH] contacts: add a view-model for SmartPanelItem controls

- adds a view-model to expose SmartPanelItem controls
- replaces SmartPanelItem control functions for finding SmartPanelItems
  originally defined in SmartPanel
- adds selection of the corresponding SmartPanelItem when calling,
  and accepting/refusing a call

Change-Id: I635a805a8e8bf6a412a6ca3d8c7ec907d3c16c2b
Tuleap: #1041
---
 ContactsViewModel.cpp           |  9 ++--
 SmartPanel.xaml.cpp             | 38 +++++-----------
 SmartPanel.xaml.h               |  3 --
 SmartPanelItemsViewModel.cpp    | 78 +++++++++++++++++++++++++++++++++
 SmartPanelItemsViewModel.h      | 68 ++++++++++++++++++++++++++++
 pch.h                           |  1 +
 ring-client-uwp.vcxproj         |  2 +
 ring-client-uwp.vcxproj.filters |  6 +++
 8 files changed, 171 insertions(+), 34 deletions(-)
 create mode 100644 SmartPanelItemsViewModel.cpp
 create mode 100644 SmartPanelItemsViewModel.h

diff --git a/ContactsViewModel.cpp b/ContactsViewModel.cpp
index f5ce48c..45cae66 100644
--- a/ContactsViewModel.cpp
+++ b/ContactsViewModel.cpp
@@ -70,8 +70,9 @@ ContactsViewModel::ContactsViewModel()
 Contact^ // refacto : remove "byName"
 ContactsViewModel::findContactByName(String^ name)
 {
+    auto trimmedName = Utils::Trim(name);
     for each (Contact^ contact in contactsList_)
-        if (contact->name_ == name)
+        if (contact->name_ == trimmedName)
             return contact;
 
     return nullptr;
@@ -80,9 +81,9 @@ ContactsViewModel::findContactByName(String^ name)
 Contact^
 ContactsViewModel::addNewContact(String^ name, String^ ringId)
 {
-    auto trimedName = Utils::Trim(name);
-    if (contactsList_ && !findContactByName(trimedName)) {
-        Contact^ contact = ref new Contact(trimedName, trimedName, nullptr, 0);
+    auto trimmedName = Utils::Trim(name);
+    if (contactsList_ && !findContactByName(trimmedName)) {
+        Contact^ contact = ref new Contact(trimmedName, trimmedName, nullptr, 0);
         contactsList_->Append(contact);
         saveContactsToFile();
         contactAdded(contact);
diff --git a/SmartPanel.xaml.cpp b/SmartPanel.xaml.cpp
index 0557bd6..022df93 100644
--- a/SmartPanel.xaml.cpp
+++ b/SmartPanel.xaml.cpp
@@ -46,8 +46,7 @@ SmartPanel::SmartPanel()
     _accountsList_->ItemsSource = AccountsViewModel::instance->accountsList;
 
     /* populate the smartlist */
-    smartPanelItemsList_ = ref new Vector<SmartPanelItem^>();
-    _smartList_->ItemsSource = smartPanelItemsList_;
+    _smartList_->ItemsSource = SmartPanelItemsViewModel::instance->itemsList;
 
     /* connect delegates */
     Configuration::UserPreferences::instance->selectIndex += ref new SelectIndex([this](int index) {
@@ -76,7 +75,7 @@ SmartPanel::SmartPanel()
             return;
         }
 
-        auto item = findItem(contact);
+        auto item = SmartPanelItemsViewModel::instance->findItem(contact);
         item->_call = call;
     });
     RingD::instance->stateChange += ref new StateChange([this](String^ callId, String^ state, int code) {
@@ -85,7 +84,7 @@ SmartPanel::SmartPanel()
         if (call == nullptr)
             return;
 
-        auto item = findItem(call);
+        auto item = SmartPanelItemsViewModel::instance->findItem(call);
 
         if (!item) {
             WNG_("item not found");
@@ -110,7 +109,7 @@ SmartPanel::SmartPanel()
     ContactsViewModel::instance->contactAdded += ref new ContactAdded([this](Contact^ contact) {
         auto smartPanelItem = ref new SmartPanelItem();
         smartPanelItem->_contact = contact;
-        smartPanelItemsList_->Append(smartPanelItem);
+        SmartPanelItemsViewModel::instance->itemsList->Append(smartPanelItem);
     });
 
     RingD::instance->calling += ref new RingClientUWP::Calling([&](
@@ -123,7 +122,7 @@ SmartPanel::SmartPanel()
             return;
         }
 
-        auto item = findItem(contact);
+        auto item = SmartPanelItemsViewModel::instance->findItem(contact);
 
         if (item == nullptr) {
             WNG_("cannot call the peer, smart panel item not found!");
@@ -300,6 +299,8 @@ void RingClientUWP::Views::SmartPanel::_rejectIncomingCallBtn__Click(Platform::O
     auto button = dynamic_cast<Button^>(e->OriginalSource);
     auto call = dynamic_cast<Call^>(button->DataContext);
 
+    _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(call);
+
     call->refuse();
 }
 
@@ -309,28 +310,9 @@ void RingClientUWP::Views::SmartPanel::_acceptIncomingCallBtn__Click(Platform::O
     auto button = dynamic_cast<Button^>(e->OriginalSource);
     auto call = dynamic_cast<Call^>(button->DataContext);
 
-    call->accept();
-}
-
-SmartPanelItem^
-SmartPanel::findItem(Contact^ contact)
-{
-    for each (SmartPanelItem^ item in smartPanelItemsList_)
-        if (item->_contact == contact)
-            return item;
-
-    return nullptr;
-}
-
-
-SmartPanelItem^
-SmartPanel::findItem(Call^ call)
-{
-    for each (SmartPanelItem^ item in smartPanelItemsList_)
-        if (item->_call == call)
-            return item;
+    _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(call);
 
-    return nullptr;
+    call->accept();
 }
 
 void
@@ -340,6 +322,8 @@ SmartPanel::_callContact__Click(Platform::Object^ sender, Windows::UI::Xaml::Rou
     auto item = dynamic_cast<SmartPanelItem^>(button->DataContext);
     auto contact = item->_contact;
 
+    _smartList_->SelectedIndex = SmartPanelItemsViewModel::instance->getIndex(contact);
+
     RingD::instance->placeCall(contact);
 }
 
diff --git a/SmartPanel.xaml.h b/SmartPanel.xaml.h
index 2d71204..121dd66 100644
--- a/SmartPanel.xaml.h
+++ b/SmartPanel.xaml.h
@@ -32,8 +32,6 @@ public ref class SmartPanel sealed
 public:
     SmartPanel();
     void updatePageContent();
-    Controls::SmartPanelItem^ findItem(Contact^ contact);
-    Controls::SmartPanelItem^ findItem(Call^ call);
 
 internal:
     enum class Mode { Minimized, Normal };
@@ -65,7 +63,6 @@ private:
     void _contactItem__PointerReleased(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
 
     /* members */
-    Vector<Controls::SmartPanelItem^>^ smartPanelItemsList_;
 };
 }
 }
\ No newline at end of file
diff --git a/SmartPanelItemsViewModel.cpp b/SmartPanelItemsViewModel.cpp
new file mode 100644
index 0000000..bdb2406
--- /dev/null
+++ b/SmartPanelItemsViewModel.cpp
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * Copyright (C) 2016 by Savoir-faire Linux                                *
+ * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com>              *
+ * Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com>          *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 3 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ **************************************************************************/
+#include "pch.h"
+
+#include "SmartPanelItemsViewModel.h"
+
+using namespace Windows::ApplicationModel::Core;
+using namespace Windows::Data::Json;
+using namespace Windows::Storage;
+using namespace Windows::Storage::Streams;
+using namespace Windows::UI::Core;
+
+
+using namespace RingClientUWP;
+using namespace ViewModel;
+
+SmartPanelItemsViewModel::SmartPanelItemsViewModel()
+{
+    itemsList_ = ref new Vector<SmartPanelItem^>();
+}
+
+SmartPanelItem^
+SmartPanelItemsViewModel::findItem(Call^ call)
+{
+    for each (SmartPanelItem^ item in itemsList)
+        if (item->_call == call)
+            return item;
+
+    return nullptr;
+}
+
+SmartPanelItem^
+SmartPanelItemsViewModel::findItem(Contact^ contact)
+{
+    for each (SmartPanelItem^ item in itemsList)
+        if (item->_contact == contact)
+            return item;
+
+    return nullptr;
+}
+
+unsigned int
+SmartPanelItemsViewModel::getIndex(Call^ call)
+{
+    unsigned int i;
+    for (i = 0; i < itemsList_->Size; i++) {
+        if (itemsList_->GetAt(i)->_call == call)
+            break;
+    }
+    return i;
+}
+
+unsigned int
+SmartPanelItemsViewModel::getIndex(Contact^ contact)
+{
+    unsigned int i;
+    for (i = 0; i < itemsList_->Size; i++) {
+        if (itemsList_->GetAt(i)->_contact == contact)
+            break;
+    }
+    return i;
+}
\ No newline at end of file
diff --git a/SmartPanelItemsViewModel.h b/SmartPanelItemsViewModel.h
new file mode 100644
index 0000000..52e1c86
--- /dev/null
+++ b/SmartPanelItemsViewModel.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * Copyright (C) 2016 by Savoir-faire Linux                                *
+ * Author: Jäger Nicolas <nicolas.jager@savoirfairelinux.com>              *
+ * Author: Traczyk Andreas <andreas.traczyk@savoirfairelinux.com>          *
+ *                                                                         *
+ * This program is free software; you can redistribute it and/or modify    *
+ * it under the terms of the GNU General Public License as published by    *
+ * the Free Software Foundation; either version 3 of the License, or       *
+ * (at your option) any later version.                                     *
+ *                                                                         *
+ * This program is distributed in the hope that it will be useful,         *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
+ * GNU General Public License for more details.                            *
+ *                                                                         *
+ * You should have received a copy of the GNU General Public License       *
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.   *
+ **************************************************************************/
+#pragma once
+
+using namespace Platform::Collections;
+using namespace Concurrency;
+
+using namespace RingClientUWP;
+using namespace RingClientUWP::Controls;
+
+namespace RingClientUWP
+{
+
+namespace ViewModel {
+public ref class SmartPanelItemsViewModel sealed
+{
+internal:
+    /* singleton */
+    static property SmartPanelItemsViewModel^ instance
+    {
+        SmartPanelItemsViewModel^ get()
+        {
+            static SmartPanelItemsViewModel^ instance_ = ref new SmartPanelItemsViewModel();
+            return instance_;
+        }
+    }
+
+    /* functions */
+    SmartPanelItem^ findItem(Call^ call);
+    SmartPanelItem^ findItem(Contact^ contact);
+    unsigned int getIndex(Call^ call);
+    unsigned int getIndex(Contact^ contact);
+
+    property Vector<SmartPanelItem^>^ itemsList
+    {
+        Vector<SmartPanelItem^>^ get()
+        {
+            return itemsList_;
+        }
+    }
+
+    /* events */
+
+private:
+    SmartPanelItemsViewModel(); // singleton
+    Vector<SmartPanelItem^>^ itemsList_;
+    SmartPanelItem^ currentItem_;
+    SmartPanelItem^ oldItem_;
+
+};
+}
+}
diff --git a/pch.h b/pch.h
index b21842f..725fb55 100644
--- a/pch.h
+++ b/pch.h
@@ -33,6 +33,7 @@
 #include "Conversation.h"
 #include "MainPage.xaml.h"
 #include "SmartPanelItem.h"
+#include "SmartPanelItemsViewModel.h"
 
 /* ensure to be accessed from anywhere */
 #include "RingD.h"
diff --git a/ring-client-uwp.vcxproj b/ring-client-uwp.vcxproj
index 21f4625..48f7621 100644
--- a/ring-client-uwp.vcxproj
+++ b/ring-client-uwp.vcxproj
@@ -190,6 +190,7 @@
       <DependentUpon>SmartPanel.xaml</DependentUpon>
     </ClInclude>
     <ClInclude Include="SmartPanelItem.h" />
+    <ClInclude Include="SmartPanelItemsViewModel.h" />
     <ClInclude Include="UserPreferences.h" />
     <ClInclude Include="Utils.h" />
     <ClInclude Include="VideoPage.xaml.h">
@@ -303,6 +304,7 @@
       <DependentUpon>SmartPanel.xaml</DependentUpon>
     </ClCompile>
     <ClCompile Include="SmartPanelItem.cpp" />
+    <ClCompile Include="SmartPanelItemsViewModel.cpp" />
     <ClCompile Include="UserPreferences.cpp" />
     <ClCompile Include="VideoPage.xaml.cpp">
       <DependentUpon>VideoPage.xaml</DependentUpon>
diff --git a/ring-client-uwp.vcxproj.filters b/ring-client-uwp.vcxproj.filters
index 974321d..8e1641b 100644
--- a/ring-client-uwp.vcxproj.filters
+++ b/ring-client-uwp.vcxproj.filters
@@ -86,6 +86,9 @@
     <ClCompile Include="SmartPanelItem.cpp">
       <Filter>Controls</Filter>
     </ClCompile>
+    <ClCompile Include="SmartPanelItemsViewModel.cpp">
+      <Filter>ModelViews</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="pch.h" />
@@ -134,6 +137,9 @@
     <ClInclude Include="SmartPanelItem.h">
       <Filter>Controls</Filter>
     </ClInclude>
+    <ClInclude Include="SmartPanelItemsViewModel.h">
+      <Filter>ModelViews</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <Image Include="Assets\LockScreenLogo.scale-200.png">
-- 
GitLab