/*
 ============================================================================
 xoblite -> an alternative shell based on Blackbox for Windows
 Copyright © 2002-2005 Karl-Henrik Henriksson [qwilk]
 Copyright © 2001-2004 The Blackbox for Windows Development Team
 http://xoblite.net/ - #bb4win on irc.freenode.net
 ============================================================================

  Blackbox for Windows is free software, released under the
  GNU General Public License (GPL version 2 or later), with an extension
  that allows linking of proprietary modules under a controlled interface.
  What this means is that plugins etc. are allowed to be released
  under any license the author wishes. Please note, however, that the
  original Blackbox gradient math code used in Blackbox for Windows
  is available under the BSD license.

  http://www.fsf.org/licenses/gpl.html
  http://www.fsf.org/licenses/gpl-faq.html#LinkingOverControlledInterface
  http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5

  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.

  For additional license information, please read the included license.html

 ============================================================================
*/

#include "../BBApi.h" 
#include "Menu.h" 
#include "MenuMaker.h" 
#include "DesktopMenu.h" 
#include "MenuItem.h" 
#include "FolderItem.h" 
#include "CommandItem.h" 
#include "../Settings.h" 
#include "../Workspaces.h" 

extern MenuMaker *pMenuMaker;
extern Settings *pSettings;
extern Workspaces *pWorkspaces;

#define DESKTOP_FOLDER_TIMER 4434 

//===========================================================================

DesktopMenu::DesktopMenu(const char *pszTitle, MenuMaker *pMenuMaker) : Menu(pMenuMaker->hInst)
{
        pMenuMaker = pMenuMaker;
        m_pszTitle = pszTitle ? strdup(pszTitle) : NULL;
}

DesktopMenu::~DesktopMenu()
{
        if(m_pszTitle) free(m_pszTitle);
        m_pszTitle = NULL;
}

//===========================================================================

void DesktopMenu::OnShow(bool fShow)
{
        if(fShow) UpdateFolder();
}

//====================

bool DesktopMenu::OnUser(int nMessage, WPARAM wParam, LPARAM lParam, LRESULT &lResult)
{
        if(nMessage == BB_DESKTOPINFO)
        {
                DesktopInfo *pDesktopInfo = (DesktopInfo *) lParam;

                DesktopMenuItem *item = new DesktopMenuItem(pDesktopInfo->name, pMenuMaker, pDesktopInfo->number);
                item->SetActivePainter(pMenuMaker->m_pSelEntry);
                item->SetPainter(pMenuMaker->m_pEntry);
                item->SetHeight(pMenuMaker->m_nSubmenuHeight);
                AddMenuItem(item);

                return true;
        }
        return Menu::OnUser(nMessage, wParam, lParam, lResult);
}

//====================

void DesktopMenu::UpdateFolder()
{
        DeleteMenuItems();

        pMenuMaker->AddHeaderItem(this, m_pszTitle);

//      DesktopMenuItem *item = new DesktopMenuItem("Iconified windows", pMenuMaker, 255);
        DesktopMenuItem *item = new DesktopMenuItem("Minimized windows", pMenuMaker, 255);
        item->SetActivePainter(pMenuMaker->m_pSelEntry);
        item->SetPainter(pMenuMaker->m_pEntry);
        item->SetHeight(pMenuMaker->m_nSubmenuHeight);
        AddMenuItem(item);

        pMenuMaker->CreateMenuItem(this, "[separator]", NULL, NULL, false);

        SendMessage(GetBBWnd(), BB_LISTDESKTOPS, (WPARAM)GetWindow(), 0);

        pMenuMaker->CreateMenuItem(this, "[separator]", NULL, NULL, false);

        pMenuMaker->CreateMenuItem(this, "[add]", NULL, "New workspace", false);
        pMenuMaker->CreateMenuItem(this, "[del]", NULL, "Remove last workspace", false);

        pMenuMaker->AddBottomItem(this);
        Invalidate();
        Validate();
}

//===========================================================================

DesktopMenuItem::DesktopMenuItem(char *pszTitle, MenuMaker *pMenuMaker, int nDesktop) : FolderItem(NULL, pszTitle)
{
        m_pMenuMaker = pMenuMaker;
        m_nDesktop = nDesktop;
        m_nTimer = 0;
}

DesktopMenuItem::~DesktopMenuItem()
{
        m_pParent->RemoveChild(m_pSubMenu); // For some reason I have to add this, delete doesn't clean it out properly...
        if (m_pSubMenu) delete m_pSubMenu;
        m_pSubMenu = NULL;
}

//===========================================================================

void DesktopMenuItem::Invoke()
{
        m_pParent->Hide(HIDE_CHILDREN);
        m_pParent->Hide(HIDE_PARENTS);
        pWorkspaces->DeskSwitch(m_nDesktop);
}

//====================

bool DesktopMenuItem::Active(bool bActivate)
{
        if(bActivate && !m_bActive)
                UpdateFolder();

        return FolderItem::Active(bActivate);
}

//====================

void DesktopMenuItem::UpdateFolder()
{
        m_pSubMenu->DeleteMenuItems();
        m_pMenuMaker->AddHeaderItem(m_pSubMenu, m_pszTitle);

        EnumWindows(CheckTaskEnumProc, (LPARAM)this);

        m_pMenuMaker->AddBottomItem(m_pSubMenu);

        m_pSubMenu->Sort(0,0);
        m_pSubMenu->Invalidate();
        m_pSubMenu->Validate();
}

//====================

void DesktopMenuItem::AddWindow(HWND hWnd)
{
        char pszWindowText[1024], wndstring[10];

        // First we get the window title text...
        GetWindowText(hWnd, pszWindowText, sizeof(pszWindowText));
        // ...then we convert its hwnd to a string with hexadecimal format... (pretty cool, eh? :D )
        _ultoa((unsigned long)hWnd, wndstring, 16);
        // Finally, we create a normal CommandItem but with the hwnd-string as argument!
        m_pMenuMaker->CreateMenuItem(m_pSubMenu, "<task_item>", wndstring, pszWindowText, false);
}

void DesktopMenuItem::Attached(Menu* pMenu)
{
        m_pParent = pMenu;
        m_pSubMenu = new Menu(m_pMenuMaker->hInst);
        m_pParent->AddChild(m_pSubMenu);
        m_pSubMenu->SetParent(m_pParent);
        SetTimer(GetWindow(), DESKTOP_FOLDER_TIMER, 2000, NULL);
}

void DesktopMenuItem::Timer(int nTimer)
{
        FolderItem::Timer(nTimer);

        if(nTimer == DESKTOP_FOLDER_TIMER && IsWindowVisible(m_pSubMenu->GetWindow()))
                UpdateFolder();
}

//===========================================================================

BOOL CALLBACK CheckTaskEnumProc(HWND hwnd, LPARAM lParam)
{
        DesktopMenuItem* pD = (DesktopMenuItem*)lParam;

        if (pD->m_nDesktop == 255) // Minimized tasks
        {
                if (IsAppWindow(hwnd) && IsIconic(hwnd)) pD->AddWindow(hwnd);
        }
        else if (pD->m_nDesktop == 254) // All tasks
        {
                if (IsAppWindow(hwnd)) pD->AddWindow(hwnd);
        }
        else // Tasks on this specific workspace
        {
                if (IsAppWindow(hwnd) && !IsIconic(hwnd))
                {
                        if (pWorkspaces->getDesktop(hwnd) == pD->m_nDesktop) pD->AddWindow(hwnd);
                }
        }

        return true;
}

//===========================================================================





syntax highlighting by

w e b c p p
web c plus plus