merge with master
[apps/osp/Internet.git] / src / IntMultipleWindowForm.cpp
1 //\r
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.\r
3 //\r
4 // Licensed under the Flora License, Version 1.0 (the License);\r
5 // you may not use this file except in compliance with the License.\r
6 // You may obtain a copy of the License at\r
7 //\r
8 //     http://floralicense.org/license/\r
9 //\r
10 // Unless required by applicable law or agreed to in writing, software\r
11 // distributed under the License is distributed on an AS IS BASIS,\r
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
13 // See the License for the specific language governing permissions and\r
14 // limitations under the License.\r
15 //\r
16 \r
17 //!Internet MultipleWindowForm class\r
18 /*@file:        MultipleWindowForm.cpp\r
19  *@brief:       The MultipleWindowForm provides multiple instance of mainscenes and displays them in a Listview\r
20  *\r
21  */\r
22 \r
23 #include <FAppUiApp.h>\r
24 #include <FUiScenes.h>\r
25 \r
26 #include "IntCommonLib.h"\r
27 #include "IntConfirmationPopup.h"\r
28 #include "IntMainForm.h"\r
29 #include "IntMultipleWindowForm.h"\r
30 #include "IntMultipleWindowPresentationModel.h"\r
31 #include "IntSceneRegister.h"\r
32 \r
33 using namespace Tizen::App;\r
34 using namespace Tizen::Base;\r
35 using namespace Tizen::Base::Collection;\r
36 using namespace Tizen::Graphics;\r
37 using namespace Tizen::Ui;\r
38 using namespace Tizen::Ui::Controls;\r
39 using namespace Tizen::Ui::Scenes;\r
40 \r
41 static const int W_ICON_IMAGE_WIDTH = 72;\r
42 \r
43 MultipleWindowForm::MultipleWindowForm(void)\r
44 : __pList(null)\r
45 , __pListIconImage(null)\r
46 , __pListDeleteImage(null)\r
47 {\r
48 }\r
49 \r
50 MultipleWindowForm::~MultipleWindowForm(void)\r
51 {\r
52         if (__pListIconImage)\r
53         {\r
54                 delete __pListIconImage;\r
55                 __pListIconImage = null;\r
56         }\r
57         if (__pListDeleteImage)\r
58         {\r
59                 delete __pListDeleteImage;\r
60                 __pListDeleteImage = null;\r
61         }\r
62 }\r
63 \r
64 bool\r
65 MultipleWindowForm::Initialize(void)\r
66 {\r
67         result r = E_SUCCESS;\r
68 \r
69         r = Construct(L"IDL_MULTIPLE_WINDOW");\r
70         if (r == E_SUCCESS)\r
71         {\r
72                 return true;\r
73         }\r
74         else\r
75         {\r
76                 return false;\r
77         }\r
78 }\r
79 \r
80 result\r
81 MultipleWindowForm::OnInitializing(void)\r
82 {\r
83         result r = E_SUCCESS;\r
84         FooterItem closeButton;\r
85         FooterItem newButton;\r
86 \r
87         SceneManager* pSceneManager = SceneManager::GetInstance();\r
88 \r
89         if (pSceneManager == null)\r
90         {\r
91                 return E_FAILURE;\r
92         }\r
93 \r
94         Footer* pFooter = GetFooter();\r
95 \r
96         if (pFooter == NULL)\r
97         {\r
98                 return E_FAILURE;\r
99         }\r
100 \r
101         SetFormStyle(FORM_STYLE_NORMAL | FORM_STYLE_INDICATOR | FORM_STYLE_HEADER | FORM_STYLE_FOOTER);\r
102 \r
103         r = pSceneManager->AddSceneEventListener(IDSCN_MULTIPLE_WINDOW, *this);\r
104 \r
105         // Setup back event listener\r
106         SetFormBackEventListener(this);\r
107         pFooter->AddActionEventListener(*this);\r
108 \r
109         AppResource* pAppResource = Application::GetInstance()->GetAppResource();\r
110 \r
111         if (pAppResource)\r
112         {\r
113                 __pListIconImage = pAppResource->GetBitmapN(L"ListIcon.png");\r
114                 __pListDeleteImage = pAppResource->GetBitmapN(L"deleteIcon.png");\r
115         }\r
116 \r
117         __pList = static_cast< ListView* >(GetControl(L"IDC_LISTVIEW"));\r
118 \r
119         if (__pList != null)\r
120         {\r
121                 __pList->SetItemProvider(*this);\r
122                 __pList->AddListViewItemEventListener(*this);\r
123         }\r
124 \r
125         AddOrientationEventListener(*this);\r
126 //      r = pFooter->SetStyle(FOOTER_STYLE_BUTTON_TEXT);\r
127         r = closeButton.Construct(IDA_BUTTON_CLOSEALL);\r
128         r = closeButton.SetText(CommonUtil::GetString(L"IDS_BR_CLOSE_ALL"));\r
129         r = pFooter->AddItem(closeButton);\r
130         r = newButton.Construct(IDA_BUTTON_NEW);\r
131         r = newButton.SetText(CommonUtil::GetString(L"IDS_BR_SK1_NEW_WINDOW"));\r
132         r = pFooter->AddItem(newButton);\r
133 \r
134         return r;\r
135 }\r
136 \r
137 void\r
138 MultipleWindowForm::OnSceneActivatedN(const SceneId& previousSceneId, const SceneId& currentSceneId, IList* pArgs)\r
139 {\r
140         if (MultipleWindowPresentationModel::GetInstance()->GetAllWindowArrayList()->GetCount() >= 9)\r
141         {\r
142                 GetFooter()->SetItemEnabled(1,false);\r
143         }\r
144         else\r
145         {\r
146                 GetFooter()->SetItemEnabled(1,true);\r
147         }\r
148         if (__pList)\r
149         {\r
150                 __pList->UpdateList();\r
151         }\r
152         GetFooter()->Invalidate(true);\r
153         return;\r
154 }\r
155 \r
156 void\r
157 MultipleWindowForm::OnSceneDeactivated(const SceneId& currentSceneId, const SceneId& nextSceneId)\r
158 {\r
159         if (__pListIconImage)\r
160         {\r
161                 delete __pListIconImage;\r
162                 __pListIconImage = NULL;\r
163         }\r
164         return;\r
165 }\r
166 \r
167 result\r
168 MultipleWindowForm::OnTerminating(void)\r
169 {\r
170         result r = E_SUCCESS;\r
171 \r
172         if (__pListIconImage)\r
173         {\r
174                 delete __pListIconImage;\r
175                 __pListIconImage = NULL;\r
176         }\r
177         if (__pListDeleteImage)\r
178         {\r
179                 delete __pListDeleteImage;\r
180                 __pListDeleteImage = NULL;\r
181         }\r
182 \r
183         return r;\r
184 }\r
185 \r
186 void\r
187 MultipleWindowForm::OnActionPerformed(const Control& source, int actionId)\r
188 {\r
189         SceneManager* pSceneManager = SceneManager::GetInstance();\r
190 \r
191         if (pSceneManager == null)\r
192         {\r
193                 return;\r
194         }\r
195 \r
196         String closeWarning = CommonUtil::GetString(L"IDS_BR_CLOSE_ALL_WINDOWS_Q");\r
197 \r
198         switch (actionId)\r
199         {\r
200         case IDA_BUTTON_NEW:\r
201         {\r
202                 WindowInfo* pNewWindowInfo = MultipleWindowPresentationModel::GetInstance()->CreateNewMainViewScene();\r
203 \r
204                 if (pNewWindowInfo == null)\r
205                 {\r
206                         return;\r
207                 }\r
208                 result r = E_SUCCESS;\r
209                 SceneManager* pSceneManager = SceneManager::GetInstance();\r
210                 if (pSceneManager == NULL)\r
211                 {\r
212                         return;\r
213                 }\r
214                 ArrayList* pArgList = new(std::nothrow) ArrayList();\r
215                 if (pArgList == NULL)\r
216                 {\r
217                         return;\r
218                 }\r
219                 pArgList->Construct();\r
220 \r
221                 pArgList->Add(*pNewWindowInfo);\r
222                 r = pSceneManager->GoForward(ForwardSceneTransition(pNewWindowInfo->sceneID, SCENE_TRANSITION_ANIMATION_TYPE_NONE),pArgList);\r
223                 if (pArgList != null)\r
224                 {\r
225                         delete pArgList;\r
226                         pArgList = null;\r
227                 }\r
228                 if(IsFailed(r))\r
229                 {\r
230                         AppLogDebug("MultipleWindowForm::OnActionPerformed GoForward failed %s",GetErrorMessage(r));\r
231                         return;\r
232                 }\r
233         }\r
234         break;\r
235 \r
236         case IDA_BUTTON_BACK:\r
237         {\r
238                 String* pSelectedScene = NULL;\r
239                 Object* value = NULL;\r
240                 MultipleWindowPresentationModel::GetInstance()->GetValue(SELECTED_SCENE_ID, &value);\r
241                 pSelectedScene = (String*) value;\r
242 \r
243                 if (pSelectedScene)\r
244                 {\r
245                         result r = pSceneManager->GoBackward(BackwardSceneTransition(*pSelectedScene, SCENE_TRANSITION_ANIMATION_TYPE_NONE));\r
246                         delete pSelectedScene;\r
247                         pSelectedScene = null;\r
248                         if(IsFailed(r))\r
249                         {\r
250                                 AppLogDebug("MultipleWindowForm::OnActionPerformed GoForward failed %s",GetErrorMessage(r));\r
251                                 return;\r
252                         }\r
253                 }\r
254         }\r
255         break;\r
256 \r
257         case IDA_BUTTON_CLOSEALL:\r
258         {\r
259                 __pConfirmationPopup = new(std::nothrow) ConfirmationPopup();\r
260                 __pConfirmationPopup->Initialize();\r
261                 __pConfirmationPopup->RemoveActionListener(*this);\r
262                 __pConfirmationPopup->AddActionListener(*this);\r
263                 __pConfirmationPopup->setMessage(closeWarning);\r
264                 __pConfirmationPopup->Show();\r
265 \r
266         }\r
267         break;\r
268         case IDA_CONFIRMATION_NO:\r
269         {\r
270                 __pConfirmationPopup->SetShowState(false);\r
271                 __pConfirmationPopup->Show();\r
272         }\r
273         break;\r
274         case IDA_CONFIRMATION_YES:\r
275         {\r
276                 ArrayList* pAllWindowList = MultipleWindowPresentationModel::GetInstance()->GetAllWindowArrayList();\r
277                 if (pAllWindowList == NULL)\r
278                 {\r
279                         return;\r
280                 }\r
281                 int totalCount = pAllWindowList->GetCount();\r
282 \r
283                 for (int count = 0; count < totalCount; count++)\r
284                 {\r
285                         WindowInfo* pWindowInfo = dynamic_cast< WindowInfo* >(pAllWindowList->GetAt(count));\r
286                         SceneRegister::DestroyAndUnRegisterScene(pWindowInfo->sceneID);\r
287                 }\r
288                 pAllWindowList->RemoveAll(true);\r
289                 WindowInfo* pNewWindowInfo = MultipleWindowPresentationModel::GetInstance()->CreateNewMainViewScene();\r
290 \r
291                 if (pNewWindowInfo == null)\r
292                 {\r
293                         return;\r
294                 }\r
295                 result r = E_SUCCESS;\r
296                 SceneManager* pSceneManager = SceneManager::GetInstance();\r
297                 if (pSceneManager == NULL)\r
298                 {\r
299                         return;\r
300                 }\r
301                 ArrayList* pArgList = new(std::nothrow) ArrayList();\r
302                 if (pArgList == NULL)\r
303                 {\r
304                         return;\r
305                 }\r
306                 r = pArgList->Construct();\r
307                 if (r == E_SUCCESS)\r
308                 {\r
309                         pArgList->Add(*pNewWindowInfo);\r
310                         result r = pSceneManager->GoForward(ForwardSceneTransition(pNewWindowInfo->sceneID, SCENE_TRANSITION_ANIMATION_TYPE_NONE),pArgList);\r
311                         if (pArgList != null)\r
312                         {\r
313                                 delete pArgList;\r
314                                 pArgList = null;\r
315                         }\r
316                         if(IsFailed(r))\r
317                         {\r
318                                 AppLogDebug("MultipleWindowForm::OnActionPerformed GoForward failed %s",GetErrorMessage(r));\r
319                                 return;\r
320                         }\r
321                 }\r
322                 __pConfirmationPopup->SetShowState(false);\r
323                 __pConfirmationPopup->Show();\r
324         }\r
325         break;\r
326         default:\r
327                 break;\r
328         }\r
329 \r
330 }\r
331 \r
332 void\r
333 MultipleWindowForm::OnFormBackRequested(Form& source)\r
334 {\r
335 \r
336         String* pSelectedScene = NULL;\r
337         Object* value = NULL;\r
338 \r
339         SceneManager* pSceneManager = SceneManager::GetInstance();\r
340         if (pSceneManager == null)\r
341         {\r
342                 return;\r
343         }\r
344 \r
345         MultipleWindowPresentationModel::GetInstance()->GetValue(SELECTED_SCENE_ID, &value);\r
346         pSelectedScene = (String*) value;\r
347         if (pSelectedScene != NULL)\r
348         {\r
349                 result r = pSceneManager->GoBackward(BackwardSceneTransition(*pSelectedScene, SCENE_TRANSITION_ANIMATION_TYPE_NONE));\r
350 //              delete pSelectedScene;\r
351                 if(IsFailed(r))\r
352                 {\r
353                         AppLogDebug("MultipleWindowForm::OnFormBackRequested GoForward failed %s",GetErrorMessage(r));\r
354                         return;\r
355                 }\r
356         }\r
357         return;\r
358 }\r
359 \r
360 void\r
361 MultipleWindowForm::OnListViewContextItemStateChanged(ListView& listView, int index, int elementId, ListContextItemStatus state)\r
362 {\r
363         return;\r
364 }\r
365 \r
366 void\r
367 MultipleWindowForm::OnListViewItemStateChanged(ListView& listView, int index, int elementId, ListItemStatus status)\r
368 {\r
369         result r = E_SUCCESS;\r
370         ArrayList* pAllWindowList = MultipleWindowPresentationModel::GetInstance()->GetAllWindowArrayList();\r
371         int count = 0;\r
372 \r
373         if (elementId == IDA_FORMAT_DELETE_BITMAP)\r
374         {\r
375                 // get current scene ID and check if it is matching with deleted scene id\r
376                 WindowInfo* pWindowInfo = dynamic_cast< WindowInfo* >(pAllWindowList->GetAt(index));\r
377                 String* pSelectedScene = NULL;\r
378                 Object* pValue = NULL;\r
379 \r
380                 if (pWindowInfo)\r
381                 {\r
382                         SceneRegister::DestroyAndUnRegisterScene(pWindowInfo->sceneID);\r
383                         MultipleWindowPresentationModel::GetInstance()->GetValue(SELECTED_SCENE_ID, &pValue);\r
384                         pSelectedScene = (String*) pValue;\r
385                         pAllWindowList->RemoveAt(index, true);\r
386                         if (pSelectedScene->CompareTo(pWindowInfo->sceneID) == 0)\r
387                         {\r
388                                 //set current scene id to last scene id\r
389                                 int totalCount = pAllWindowList->GetCount() - 1;\r
390                                 WindowInfo* pLastIndexWindowInfo = dynamic_cast< WindowInfo* >(pAllWindowList->GetAt(totalCount));\r
391                                 if (pLastIndexWindowInfo != NULL)\r
392                                 {\r
393                                         String* pSelectedSceneID = new(std::nothrow) String(pLastIndexWindowInfo->sceneID);\r
394                                         if (pSelectedSceneID != NULL)\r
395                                         {\r
396                                                 MultipleWindowPresentationModel::GetInstance()->SetValue(SELECTED_SCENE_ID, (Object*) pSelectedSceneID);\r
397 \r
398                                         }\r
399                                 }\r
400                         }\r
401                 }\r
402 \r
403                 count = MultipleWindowPresentationModel::GetInstance()->GetInstance()->GetAllWindowArrayList()->GetCount();\r
404 \r
405                 if (count >= 9)\r
406                 {\r
407                         GetFooter()->SetItemEnabled(1,false);\r
408                 }\r
409                 else\r
410                 {\r
411                         GetFooter()->SetItemEnabled(1,true);\r
412                 }\r
413 \r
414                 if ( count <= 1)\r
415                 {\r
416                         GetFooter()->SetItemEnabled(0,false);\r
417                 }\r
418 \r
419                 GetFooter()->Invalidate(true);\r
420                 __pList->RefreshList(index, LIST_REFRESH_TYPE_ITEM_REMOVE);\r
421                 __pList->UpdateList();\r
422         }\r
423         else if(elementId == IDA_FORMAT_BITMAP || elementId == IDA_FORMAT_TITLE_STRING\r
424                         || elementId == IDA_FORMAT_URL_STRING || elementId == -1)\r
425         {\r
426 \r
427                 // launch the browser\r
428                 WindowInfo* pWindowInfo = dynamic_cast< WindowInfo* >(pAllWindowList->GetAt(index));\r
429                 if (pWindowInfo == NULL)\r
430                 {\r
431                         return;\r
432                 }\r
433                 SceneManager* pSceneManager = SceneManager::GetInstance();\r
434                 if (pSceneManager == NULL)\r
435                 {\r
436                         return;\r
437                 }\r
438                 ArrayList* pArgList = new(std::nothrow) ArrayList();\r
439                 if (pArgList == NULL)\r
440                 {\r
441                         return;\r
442                 }\r
443                 r = pArgList->Construct();\r
444                 if (IsFailed(r))\r
445                 {\r
446                         return;\r
447                 }\r
448                 pArgList->Add(*pWindowInfo);\r
449                 result r = pSceneManager->GoForward(ForwardSceneTransition(pWindowInfo->sceneID, SCENE_TRANSITION_ANIMATION_TYPE_NONE),pArgList);\r
450 \r
451                 if (r == E_SUCCESS)\r
452                 {\r
453                         AppLogDebug("go forward success");\r
454                 }\r
455                 else\r
456                 {\r
457                         AppLogDebug("go forward failed");\r
458                 }\r
459                 if (pArgList != null)\r
460                 {\r
461                         delete pArgList;\r
462                         pArgList = null;\r
463                 }\r
464 \r
465         }\r
466 \r
467         return;\r
468 }\r
469 \r
470 void\r
471 MultipleWindowForm::OnListViewItemSwept(ListView& listView, int index, SweepDirection direction)\r
472 {\r
473         return;\r
474 }\r
475 \r
476 void\r
477 MultipleWindowForm::OnListViewItemLongPressed(ListView& listView, int index, int elementId, bool& invokeListViewItemCallback)\r
478 {\r
479         return;\r
480 }\r
481 \r
482 ListItemBase*\r
483 MultipleWindowForm::CreateItem(int index, int itemWidth)\r
484 {\r
485         Rectangle listImageRect;\r
486         Rectangle pagetTitleRect;\r
487         Rectangle pageURLRect;\r
488         Rectangle deleteImageRect;\r
489         String pageTitle(L"");\r
490         String pageURL(L"");\r
491         result r = E_SUCCESS;\r
492         int width = W_ICON_IMAGE_WIDTH;\r
493 \r
494         AppResource* pAppResource = Application::GetInstance()->GetAppResource();\r
495         ListAnnexStyle style = LIST_ANNEX_STYLE_NORMAL;\r
496         ArrayList* pAllWindowList = MultipleWindowPresentationModel::GetInstance()->GetAllWindowArrayList();\r
497 \r
498         if (pAllWindowList == null)\r
499         {\r
500                 return null;\r
501         }\r
502         WindowInfo* pWindowInfo = dynamic_cast< WindowInfo* >(pAllWindowList->GetAt(index));\r
503         if(pWindowInfo == null)\r
504         {\r
505                 return NULL;\r
506         }\r
507         CustomItem* pItem = new(std::nothrow) CustomItem();\r
508         pageTitle = pWindowInfo->pageTitle;\r
509         pageURL = pWindowInfo->pageUrl;\r
510         if (pageURL.GetLength() == 0)\r
511         {\r
512                 String nourl;\r
513                 pAppResource->GetString(L"IDS_BR_BODY_ABOUT_C_BLANK", nourl);\r
514                 pageURL = L"<"+ nourl +">";\r
515         }\r
516 \r
517         Rectangle screenBounds = GetBounds();\r
518         r = pItem->Construct(Dimension(itemWidth, 128), style);\r
519         if (IsFailed(r))\r
520         {\r
521                 return NULL;\r
522         }\r
523 \r
524         if (pWindowInfo->pFavicon)\r
525         {\r
526 \r
527                 if( __pListIconImage != NULL)\r
528                 {\r
529                         delete __pListIconImage;\r
530                         __pListIconImage = null;\r
531                 }\r
532 \r
533                 __pListIconImage = new Bitmap();\r
534                 __pListIconImage->Construct(*(pWindowInfo->pFavicon),Rectangle(0,0,pWindowInfo->pFavicon->GetWidth(),pWindowInfo->pFavicon->GetHeight()));\r
535         }\r
536         else\r
537         {\r
538                 if( __pListIconImage != NULL)\r
539                 {\r
540                         delete __pListIconImage;\r
541                         __pListIconImage = null;\r
542                 }\r
543 \r
544                 __pListIconImage = pAppResource->GetBitmapN(L"I01_icon_default_favicon.png");\r
545         }\r
546         AppLog("deleteimg %d %d",__pListDeleteImage->GetWidth(),__pListDeleteImage->GetHeight());\r
547 \r
548         listImageRect.SetBounds(screenBounds.x + 16, screenBounds.y + 28,width, 72);\r
549         pagetTitleRect.SetBounds(listImageRect.x + width + 16,10, screenBounds.width - 2 * width - 64, 60);\r
550         pageURLRect.SetBounds(pagetTitleRect.x, pagetTitleRect.y + pagetTitleRect.height, screenBounds.width - 2 * width - 120, 48);\r
551         deleteImageRect.SetBounds(screenBounds.width - __pListDeleteImage->GetWidth() - 24, (128 - __pListDeleteImage->GetHeight() - 8)/2, __pListDeleteImage->GetWidth() + 8, __pListDeleteImage->GetHeight() + 8);\r
552         pItem->AddElement(listImageRect, IDA_FORMAT_BITMAP, *__pListIconImage, null, null);\r
553 \r
554         if (pageTitle.CompareTo(L"") != 0)\r
555         {\r
556                 pItem->AddElement(pagetTitleRect, IDA_FORMAT_TITLE_STRING, pageTitle, 44, CUSTOM_COLOR_TRANSPARENT, CUSTOM_COLOR_TRANSPARENT, CUSTOM_COLOR_TRANSPARENT, true);\r
557         }\r
558 \r
559         if (pageURL.CompareTo(L"") != 0)\r
560         {\r
561                 pItem->AddElement(pageURLRect, IDA_FORMAT_URL_STRING, pageURL, 32, CUSTOM_COLOR_GREY, CUSTOM_COLOR_GREY, CUSTOM_COLOR_GREY, true);\r
562         }\r
563 \r
564         if (pAllWindowList)\r
565         {\r
566                 if (pAllWindowList->GetCount() > 1)\r
567                 {\r
568                         pItem->AddElement(deleteImageRect, IDA_FORMAT_DELETE_BITMAP, *__pListDeleteImage, null, null);\r
569                         pItem->SetElementSelectionEnabled(IDA_FORMAT_DELETE_BITMAP, true);                      \r
570                 }\r
571         }\r
572         return pItem;\r
573 }\r
574 \r
575 bool\r
576 MultipleWindowForm::DeleteItem(int index, ListItemBase* pItem, int itemWidth)\r
577 {\r
578         delete pItem;\r
579         pItem = null;\r
580         return true;\r
581 }\r
582 \r
583 int\r
584 MultipleWindowForm::GetItemCount(void)\r
585 {\r
586         ArrayList* pAllWindowList = MultipleWindowPresentationModel::GetInstance()->GetAllWindowArrayList();\r
587         int windowCount = 0;\r
588 \r
589         if (pAllWindowList != null)\r
590         {\r
591                 windowCount = pAllWindowList->GetCount();\r
592         }\r
593         if (windowCount < 2)\r
594         {\r
595                 GetFooter()->SetItemEnabled(0, false);\r
596         }\r
597         else\r
598         {\r
599                 GetFooter()->SetItemEnabled(0, true);\r
600         }\r
601         GetFooter()->Invalidate(true);\r
602         return windowCount;\r
603 }\r
604 \r
605 void\r
606 MultipleWindowForm::OnOrientationChanged(const Control& source, OrientationStatus orientationStatus)\r
607 {\r
608         if (__pList)\r
609         {\r
610                 __pList->UpdateList();\r
611         }\r
612 }\r