#include "../../../stdafx.h"
#include "GUIPythonWindowXML.h"
#include "guiwindow.h"
#include "pyutil.h"
#include "..\..\..\application.h"
#include "..\..\..\GUIMediaWindow.h"
#include "window.h"
#include "control.h"
#include "action.h"
#define CONTROL_BTNVIEWASICONS 2
#define CONTROL_BTNSORTBY 3
#define CONTROL_BTNSORTASC 4
#define CONTROL_LIST 50
#define CONTROL_LABELFILES 12
#define CONTROL_VIEW_START 50
#define CONTROL_VIEW_END 59
using namespace PYXBMC;
CGUIPythonWindowXML::CGUIPythonWindowXML(DWORD dwId, CStdString strXML, CStdString strFallBackPath)
: CGUIWindow(dwId,strXML)
{
pCallbackWindow = NULL;
m_actionEvent = CreateEvent(NULL, true, false, NULL);
m_loadOnDemand = false;
m_guiState.reset(CGUIViewState::GetViewState(GetID(), m_vecItems));
m_coordsRes = PAL_4x3;
m_fallbackPath = strFallBackPath;
}
CGUIPythonWindowXML::~CGUIPythonWindowXML(void)
{
CloseHandle(m_actionEvent);
}
void CGUIPythonWindowXML::Update()
{
}
bool CGUIPythonWindowXML::OnAction(const CAction &action)
{
// do the base class window first, and the call to python after this
bool ret = CGUIWindow::OnAction(action);
if(pCallbackWindow)
{
PyXBMCAction* inf = new PyXBMCAction;
inf->pObject = Action_FromAction(action);
inf->pCallbackWindow = pCallbackWindow;
// aquire lock?
Py_AddPendingCall(Py_XBMC_Event_OnAction, inf);
PulseActionEvent();
}
return ret;
}
void CGUIPythonWindowXML::OnWindowLoaded()
{
CGUIWindow::OnWindowLoaded();
m_viewControl.Reset();
m_viewControl.SetParentWindow(GetID());
for (int i = CONTROL_VIEW_START; i <= CONTROL_VIEW_END; i++)
{
m_viewControl.AddView(GetControl(i));
}
m_viewControl.SetViewControlID(CONTROL_BTNVIEWASICONS);
UpdateButtons();
}
bool CGUIPythonWindowXML::OnMessage(CGUIMessage& message)
{
switch (message.GetMessage())
{
case GUI_MSG_WINDOW_DEINIT:
{
m_gWindowManager.ShowOverlay(OVERLAY_STATE_SHOWN);
}
break;
case GUI_MSG_WINDOW_INIT:
{
CGUIWindow::OnMessage(message);
m_gWindowManager.ShowOverlay(OVERLAY_STATE_HIDDEN);
PyXBMCAction* inf = new PyXBMCAction;
inf->pObject = NULL;
// create a new call and set it in the python queue
inf->pCallbackWindow = pCallbackWindow;
Py_AddPendingCall(Py_XBMC_Event_OnInit, inf);
return true;
}
break;
case GUI_MSG_SETFOCUS:
{
if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != message.GetControlId())
{
m_viewControl.SetFocused();
return true;
}
// check if our focused control is one of our category buttons
int iControl=message.GetControlId();
if(pCallbackWindow)
{
PyXBMCAction* inf = new PyXBMCAction;
inf->pObject = NULL;
// create a new call and set it in the python queue
inf->pCallbackWindow = pCallbackWindow;
inf->controlId = iControl;
// aquire lock?
Py_AddPendingCall(Py_XBMC_Event_OnFocus, inf);
PulseActionEvent();
}
}
break;
case GUI_MSG_CLICKED:
{
int iControl=message.GetSenderId();
// Handle Sort/View internally. Scripters shouldn't use ID 2, 3 or 4.
if (iControl == CONTROL_BTNVIEWASICONS)
{
if (m_guiState.get())
{
m_guiState->SaveViewAsControl(m_viewControl.GetNextViewMode());
}
UpdateButtons();
return true;
}
else if (iControl == CONTROL_BTNSORTASC) // sort asc
{
CLog::Log(LOGINFO,"WindowXML: Internal asc/dsc button not implemented");
/*if (m_guiState.get())
m_guiState->SetNextSortOrder();
UpdateFileList();*/
return true;
}
else if (iControl == CONTROL_BTNSORTBY) // sort by
{
CLog::Log(LOGINFO,"WindowXML: Internal sort button not implemented");
/*if (m_guiState.get())
m_guiState->SetNextSortMethod();
UpdateFileList();*/
return true;
}
if(pCallbackWindow && iControl && iControl != this->GetID()) // pCallbackWindow && != this->GetID())
{
CGUIControl* controlClicked = (CGUIControl*)this->GetControl(iControl);
// The old python way used to check list AND SELECITEM method or if its a button, checkmark.
// Its done this way for now to allow other controls without a python version like togglebutton to still raise a onAction event
if (controlClicked) // Will get problems if we the id is not on the window and we try to do GetControlType on it. So check to make sure it exists
{
if (controlClicked->GetControlType() == CGUIControl::GUICONTAINER_LIST && message.GetParam1() == ACTION_SELECT_ITEM || controlClicked->GetControlType() != CGUIControl::GUICONTAINER_LIST)
{
PyXBMCAction* inf = new PyXBMCAction;
inf->pObject = NULL;
// create a new call and set it in the python queue
inf->pCallbackWindow = pCallbackWindow;
inf->controlId = iControl;
// aquire lock?
Py_AddPendingCall(Py_XBMC_Event_OnClick, inf);
PulseActionEvent();
}
}
}
}
break;
}
return CGUIWindow::OnMessage(message);
}
void CGUIPythonWindowXML::AddItem(CFileItem * fileItem,int intPosition)
{
if (intPosition == 0) m_vecItems.AddFront(fileItem);
else if (intPosition == -1)m_vecItems.Add(fileItem);
else
{
if (intPosition > m_vecItems.Size())return;
CFileItemList*orgVecItems = new CFileItemList(m_vecItems);
m_vecItems.Clear();
for (int i = 0; i < orgVecItems->Size(); ++i)
if (i == intPosition){
m_vecItems.Add(fileItem);}
m_vecItems.Add(&orgVecItems[i]);
}
m_viewControl.SetItems(m_vecItems);
UpdateButtons();
}
void CGUIPythonWindowXML::RemoveItem(int itemPosition)
{
m_vecItems.Remove(itemPosition);
m_viewControl.SetItems(m_vecItems);
UpdateButtons();
}
int CGUIPythonWindowXML::GetCurrentListPosition()
{
return m_viewControl.GetSelectedItem();
}
void CGUIPythonWindowXML::SetCurrentListPosition(int item)
{
return m_viewControl.SetSelectedItem(item);
}
CFileItem * CGUIPythonWindowXML::GetListItem(int position)
{
CFileItem * selectedItem = new CFileItem("Item Index doesn't exist");
if (position < m_vecItems.Size())
{
selectedItem = m_vecItems[position];
}
return selectedItem;
}
void CGUIPythonWindowXML::RefreshList()
{
m_viewControl.SetItems(m_vecItems);
UpdateButtons();
}
void CGUIPythonWindowXML::ClearList()
{
m_viewControl.Clear();
m_vecItems.Clear();
m_viewControl.SetItems(m_vecItems);
UpdateButtons();
}
void CGUIPythonWindowXML::WaitForActionEvent(DWORD timeout)
{
WaitForSingleObject(m_actionEvent, timeout);
ResetEvent(m_actionEvent);
}
void CGUIPythonWindowXML::PulseActionEvent()
{
SetEvent(m_actionEvent);
}
void CGUIPythonWindowXML::Render()
{
string backupMediaDir = g_graphicsContext.GetMediaDir();
g_graphicsContext.SetMediaDir(m_fallbackPath+"\\skins");
CGUIWindow::Render();
g_graphicsContext.SetMediaDir(backupMediaDir);
}
int Py_XBMC_Event_OnClick(void* arg)
{
if (arg != NULL)
{
PyXBMCAction* action = (PyXBMCAction*)arg;
PyObject_CallMethod(action->pCallbackWindow, "onClick", "i", action->controlId);
delete action;
}
return 0;
}
int Py_XBMC_Event_OnFocus(void* arg)
{
if (arg != NULL)
{
PyXBMCAction* action = (PyXBMCAction*)arg;
PyObject_CallMethod(action->pCallbackWindow, "onFocus", "i", action->controlId);
delete action;
}
return 0;
}
int Py_XBMC_Event_OnInit(void* arg)
{
if (arg != NULL)
{
PyXBMCAction* action = (PyXBMCAction*)arg;
PyObject_CallMethod(action->pCallbackWindow, "onInit",""); //, "O", &self);
delete action;
}
return 0;
}
/// Functions Below here are speceifc for the 'MediaWindow' Like stuff (such as Sort and View)
// \brief Prepares and adds the fileitems list/thumb panel
void CGUIPythonWindowXML::OnSort()
{
FormatItemLabels();
SortItems(m_vecItems);
}
// \brief Formats item labels based on the formatting provided by guiViewState
void CGUIPythonWindowXML::FormatItemLabels()
{
if (!m_guiState.get())
return;
CGUIViewState::LABEL_MASKS labelMasks;
m_guiState->GetSortMethodLabelMasks(labelMasks);
}
// \brief Sorts Fileitems based on the sort method and sort oder provided by guiViewState
void CGUIPythonWindowXML::SortItems(CFileItemList &items)
{
auto_ptr<CGUIViewState> guiState(CGUIViewState::GetViewState(GetID(), items));
if (guiState.get())
{
items.Sort(guiState->GetSortMethod(), guiState->GetDisplaySortOrder());
// Should these items be saved to the hdd
if (items.GetCacheToDisc())
items.Save();
}
}
// \brief Synchonize the fileitems with the playlistplayer
// It recreated the playlist of the playlistplayer based
// on the fileitems of the window
void CGUIPythonWindowXML::UpdateFileList()
{
int nItem = m_viewControl.GetSelectedItem();
CFileItem* pItem = m_vecItems[nItem];
const CStdString& strSelected = pItem->m_strPath;
OnSort();
UpdateButtons();
m_viewControl.SetItems(m_vecItems);
m_viewControl.SetSelectedItem(strSelected);
}
// \brief Updates the states (enable, disable, visible...)
// of the controls defined by this window
// Override this function in a derived class to add new controls
void CGUIPythonWindowXML::UpdateButtons()
{
if (m_guiState.get())
{
// Update sorting controls
if (m_guiState->GetDisplaySortOrder()==SORT_ORDER_NONE)
{
CONTROL_DISABLE(CONTROL_BTNSORTASC);
}
else
{
CONTROL_ENABLE(CONTROL_BTNSORTASC);
if (m_guiState->GetDisplaySortOrder()==SORT_ORDER_ASC)
{
CGUIMessage msg(GUI_MSG_DESELECTED, GetID(), CONTROL_BTNSORTASC);
g_graphicsContext.SendMessage(msg);
}
else
{
CGUIMessage msg(GUI_MSG_SELECTED, GetID(), CONTROL_BTNSORTASC);
g_graphicsContext.SendMessage(msg);
}
}
// Update list/thumb control
m_viewControl.SetCurrentView(m_guiState->GetViewAsControl());
// Update sort by button
if (m_guiState->GetSortMethod()==SORT_METHOD_NONE)
{
CONTROL_DISABLE(CONTROL_BTNSORTBY);
}
else
{
CONTROL_ENABLE(CONTROL_BTNSORTBY);
}
CStdString sortLabel;
sortLabel.Format(g_localizeStrings.Get(550).c_str(), g_localizeStrings.Get(m_guiState->GetSortMethodLabel()).c_str());
SET_CONTROL_LABEL(CONTROL_BTNSORTBY, sortLabel);
}
int iItems = m_vecItems.Size();
if (iItems)
{
CFileItem* pItem = m_vecItems[0];
if (pItem->IsParentFolder()) iItems--;
}
CStdString items;
items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str());
SET_CONTROL_LABEL(CONTROL_LABELFILES, items);
}
void CGUIPythonWindowXML::OnInitWindow()
{
// Update list/thumb control
m_viewControl.SetCurrentView(DEFAULT_VIEW_LIST);
m_viewControl.SetFocused();
SET_CONTROL_VISIBLE(CONTROL_LIST);
CGUIWindow::OnInitWindow();
}
CGUIControl *CGUIPythonWindowXML::GetFirstFocusableControl(int id)
{
if (m_viewControl.HasControl(id))
id = m_viewControl.GetCurrentControl();
return CGUIWindow::GetFirstFocusableControl(id);
}