2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIDialogSelect.h"
12 #include "FileItemList.h"
13 #include "guilib/GUIMessage.h"
14 #include "guilib/LocalizeStrings.h"
15 #include "input/actions/ActionIDs.h"
16 #include "utils/StringUtils.h"
20 #define CONTROL_HEADING 1
21 #define CONTROL_NUMBER_OF_ITEMS 2
22 #define CONTROL_SIMPLE_LIST 3
23 #define CONTROL_DETAILED_LIST 6
24 #define CONTROL_EXTRA_BUTTON 5
25 #define CONTROL_EXTRA_BUTTON2 8
26 #define CONTROL_CANCEL_BUTTON 7
28 CGUIDialogSelect::CGUIDialogSelect() : CGUIDialogSelect(WINDOW_DIALOG_SELECT
) {}
30 CGUIDialogSelect::CGUIDialogSelect(int windowId
)
31 : CGUIDialogBoxBase(windowId
, "DialogSelect.xml"),
32 m_vecList(std::make_unique
<CFileItemList
>()),
33 m_bButtonEnabled(false),
34 m_bButton2Enabled(false),
35 m_bButtonPressed(false),
36 m_bButton2Pressed(false),
38 m_multiSelection(false)
41 m_loadType
= KEEP_IN_MEMORY
;
44 CGUIDialogSelect::~CGUIDialogSelect(void) = default;
46 bool CGUIDialogSelect::OnMessage(CGUIMessage
& message
)
48 switch (message
.GetMessage())
50 case GUI_MSG_WINDOW_DEINIT
:
52 CGUIDialogBoxBase::OnMessage(message
);
54 m_bButtonEnabled
= false;
55 m_bButton2Enabled
= false;
57 m_multiSelection
= false;
59 // construct selected items list
60 m_selectedItems
.clear();
61 m_selectedItem
= nullptr;
62 for (int i
= 0 ; i
< m_vecList
->Size() ; i
++)
64 CFileItemPtr item
= m_vecList
->Get(i
);
65 if (item
->IsSelected())
67 m_selectedItems
.push_back(i
);
69 m_selectedItem
= item
;
77 case GUI_MSG_WINDOW_INIT
:
79 m_bButtonPressed
= false;
80 m_bButton2Pressed
= false;
82 CGUIDialogBoxBase::OnMessage(message
);
90 int iControl
= message
.GetSenderId();
91 if (m_viewControl
.HasControl(CONTROL_SIMPLE_LIST
))
93 int iAction
= message
.GetParam1();
94 if (ACTION_SELECT_ITEM
== iAction
|| ACTION_MOUSE_LEFT_CLICK
== iAction
)
96 int iSelected
= m_viewControl
.GetSelectedItem();
97 if (iSelected
>= 0 && iSelected
< m_vecList
->Size())
99 CFileItemPtr
item(m_vecList
->Get(iSelected
));
100 if (m_multiSelection
)
101 item
->Select(!item
->IsSelected());
104 for (int i
= 0 ; i
< m_vecList
->Size() ; i
++)
105 m_vecList
->Get(i
)->Select(false);
112 if (iControl
== CONTROL_EXTRA_BUTTON2
)
114 m_bButton2Pressed
= true;
115 if (m_multiSelection
)
119 if (iControl
== CONTROL_EXTRA_BUTTON
)
121 m_selectedItem
= nullptr;
122 m_bButtonPressed
= true;
123 if (m_multiSelection
)
127 else if (iControl
== CONTROL_CANCEL_BUTTON
)
129 m_selectedItem
= nullptr;
131 m_selectedItems
.clear();
132 m_bConfirmed
= false;
137 case GUI_MSG_SETFOCUS
:
139 if (m_viewControl
.HasControl(message
.GetControlId()))
141 if (m_vecList
->IsEmpty())
143 if (m_bButtonEnabled
)
144 SET_CONTROL_FOCUS(CONTROL_EXTRA_BUTTON
, 0);
146 SET_CONTROL_FOCUS(CONTROL_CANCEL_BUTTON
, 0);
149 if (m_viewControl
.GetCurrentControl() != message
.GetControlId())
151 m_viewControl
.SetFocused();
159 return CGUIDialogBoxBase::OnMessage(message
);
162 void CGUIDialogSelect::OnSelect(int idx
)
168 bool CGUIDialogSelect::OnBack(int actionID
)
170 m_selectedItem
= nullptr;
172 m_selectedItems
.clear();
173 m_bConfirmed
= false;
174 return CGUIDialogBoxBase::OnBack(actionID
);
177 void CGUIDialogSelect::Reset()
179 m_bButtonEnabled
= false;
180 m_bButtonPressed
= false;
181 m_bButton2Enabled
= false;
182 m_bButton2Pressed
= false;
184 m_useDetails
= false;
185 m_multiSelection
= false;
186 m_focusToButton
= false;
187 m_selectedItem
= nullptr;
189 m_selectedItems
.clear();
192 int CGUIDialogSelect::Add(const std::string
& strLabel
)
194 CFileItemPtr
pItem(new CFileItem(strLabel
));
195 m_vecList
->Add(pItem
);
196 return m_vecList
->Size() - 1;
199 int CGUIDialogSelect::Add(const CFileItem
& item
)
201 m_vecList
->Add(std::make_shared
<CFileItem
>(item
));
202 return m_vecList
->Size() - 1;
205 void CGUIDialogSelect::SetItems(const CFileItemList
& pList
)
208 m_vecList
->Append(pList
);
210 m_viewControl
.SetItems(*m_vecList
);
213 int CGUIDialogSelect::GetSelectedItem() const
215 return m_selectedItems
.size() > 0 ? m_selectedItems
[0] : -1;
218 const CFileItemPtr
CGUIDialogSelect::GetSelectedFileItem() const
221 return m_selectedItem
;
222 return std::make_shared
<CFileItem
>();
225 const std::vector
<int>& CGUIDialogSelect::GetSelectedItems() const
227 return m_selectedItems
;
230 void CGUIDialogSelect::EnableButton(bool enable
, int label
)
232 m_bButtonEnabled
= enable
;
233 m_buttonLabel
= g_localizeStrings
.Get(label
);
236 void CGUIDialogSelect::EnableButton(bool enable
, const std::string
& label
)
238 m_bButtonEnabled
= enable
;
239 m_buttonLabel
= label
;
242 void CGUIDialogSelect::EnableButton2(bool enable
, int label
)
244 m_bButton2Enabled
= enable
;
245 m_button2Label
= g_localizeStrings
.Get(label
);
248 void CGUIDialogSelect::EnableButton2(bool enable
, const std::string
& label
)
250 m_bButton2Enabled
= enable
;
251 m_button2Label
= label
;
254 bool CGUIDialogSelect::IsButtonPressed()
256 return m_bButtonPressed
;
259 bool CGUIDialogSelect::IsButton2Pressed()
261 return m_bButton2Pressed
;
264 void CGUIDialogSelect::Sort(bool bSortOrder
/*=true*/)
266 m_vecList
->Sort(SortByLabel
, bSortOrder
? SortOrderAscending
: SortOrderDescending
);
269 void CGUIDialogSelect::SetSelected(int iSelected
)
271 if (iSelected
< 0 || iSelected
>= m_vecList
->Size() ||
272 m_vecList
->Get(iSelected
).get() == NULL
)
275 // only set m_iSelected if there is no multi-select
276 // or if it doesn't have a valid value yet
277 // or if the current value is bigger than the new one
278 // so that we always focus the item nearest to the beginning of the list
279 if (!m_multiSelection
|| !m_selectedItem
||
280 (!m_selectedItems
.empty() && m_selectedItems
.back() > iSelected
))
281 m_selectedItem
= m_vecList
->Get(iSelected
);
282 m_vecList
->Get(iSelected
)->Select(true);
283 m_selectedItems
.push_back(iSelected
);
286 void CGUIDialogSelect::SetSelected(const std::string
&strSelectedLabel
)
288 for (int index
= 0; index
< m_vecList
->Size(); index
++)
290 if (strSelectedLabel
== m_vecList
->Get(index
)->GetLabel())
298 void CGUIDialogSelect::SetSelected(const std::vector
<int>& selectedIndexes
)
300 for (auto i
: selectedIndexes
)
304 void CGUIDialogSelect::SetSelected(const std::vector
<std::string
> &selectedLabels
)
306 for (const auto& label
: selectedLabels
)
310 void CGUIDialogSelect::SetUseDetails(bool useDetails
)
312 m_useDetails
= useDetails
;
315 void CGUIDialogSelect::SetMultiSelection(bool multiSelection
)
317 m_multiSelection
= multiSelection
;
320 void CGUIDialogSelect::SetButtonFocus(bool buttonFocus
)
322 m_focusToButton
= buttonFocus
;
325 CGUIControl
*CGUIDialogSelect::GetFirstFocusableControl(int id
)
327 if (m_viewControl
.HasControl(id
))
328 id
= m_viewControl
.GetCurrentControl();
329 return CGUIDialogBoxBase::GetFirstFocusableControl(id
);
332 void CGUIDialogSelect::OnWindowLoaded()
334 CGUIDialogBoxBase::OnWindowLoaded();
335 m_viewControl
.Reset();
336 m_viewControl
.SetParentWindow(GetID());
337 m_viewControl
.AddView(GetControl(CONTROL_SIMPLE_LIST
));
338 m_viewControl
.AddView(GetControl(CONTROL_DETAILED_LIST
));
341 void CGUIDialogSelect::OnInitWindow()
343 m_viewControl
.SetItems(*m_vecList
);
344 m_selectedItems
.clear();
345 for(int i
= 0 ; i
< m_vecList
->Size(); i
++)
347 auto item
= m_vecList
->Get(i
);
348 if (item
->IsSelected())
350 m_selectedItems
.push_back(i
);
351 if (m_selectedItem
== nullptr)
352 m_selectedItem
= item
;
355 m_viewControl
.SetCurrentView(m_useDetails
? CONTROL_DETAILED_LIST
: CONTROL_SIMPLE_LIST
);
357 SET_CONTROL_LABEL(CONTROL_NUMBER_OF_ITEMS
,
358 StringUtils::Format("{} {}", m_vecList
->Size(), g_localizeStrings
.Get(127)));
360 if (m_multiSelection
)
361 EnableButton(true, 186);
363 if (m_bButtonEnabled
)
365 SET_CONTROL_LABEL(CONTROL_EXTRA_BUTTON
, m_buttonLabel
);
366 SET_CONTROL_VISIBLE(CONTROL_EXTRA_BUTTON
);
369 SET_CONTROL_HIDDEN(CONTROL_EXTRA_BUTTON
);
371 if (m_bButton2Enabled
)
373 SET_CONTROL_LABEL(CONTROL_EXTRA_BUTTON2
, m_button2Label
);
374 SET_CONTROL_VISIBLE(CONTROL_EXTRA_BUTTON2
);
377 SET_CONTROL_HIDDEN(CONTROL_EXTRA_BUTTON2
);
379 SET_CONTROL_LABEL(CONTROL_CANCEL_BUTTON
, g_localizeStrings
.Get(222));
381 CGUIDialogBoxBase::OnInitWindow();
383 // focus one of the buttons if explicitly requested
384 // ATTENTION: this must be done after calling CGUIDialogBoxBase::OnInitWindow()
387 if (m_bButtonEnabled
)
388 SET_CONTROL_FOCUS(CONTROL_EXTRA_BUTTON
, 0);
390 SET_CONTROL_FOCUS(CONTROL_CANCEL_BUTTON
, 0);
393 // if nothing is selected, select first item
394 m_viewControl
.SetSelectedItem(std::max(GetSelectedItem(), 0));
397 void CGUIDialogSelect::OnDeinitWindow(int nextWindowID
)
399 m_viewControl
.Clear();
400 CGUIDialogBoxBase::OnDeinitWindow(nextWindowID
);
403 void CGUIDialogSelect::OnWindowUnload()
405 CGUIDialogBoxBase::OnWindowUnload();
406 m_viewControl
.Reset();