/*
 ============================================================================
 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 "FolderItem.h" 
#include "Menu.h" 
#include "MenuMaker.h" 
#include "TitleItem.h" 
#include "Painter.h" 
#include "../Settings.h" 

extern MenuMaker *pMenuMaker;
extern Settings *pSettings;

int FolderItem::m_nBulletPosition = DT_RIGHT;
int FolderItem::m_nBulletStyle = BS_TRIANGLE;

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

FolderItem::FolderItem(Menu* pSubMenu, char* pszTitle) : TitleItem(pszTitle, MENU_DEFAULT)
{
        m_pSubMenu = pSubMenu;
        m_nTimerId = 0;
        m_nSortPriority = 10;
}

FolderItem::~FolderItem()
{
        if(m_pSubMenu) delete m_pSubMenu;
        m_pSubMenu = NULL;
}

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

// Paints the folder item, the parent class will paint first
void FolderItem::Paint(HDC hDC)
{
        TitleItem::Paint(hDC);
        if (m_nBulletStyle == BS_TRIANGLE) PaintTriangleBullet(hDC, m_nTop);
        else if (m_nBulletStyle == BS_SQUARE) PaintSquareBullet(hDC, m_nTop);
        else if (m_nBulletStyle == BS_DIAMOND) PaintDiamondBullet(hDC, m_nTop);
        else if (m_nBulletStyle == BS_CIRCLE) PaintCircleBullet(hDC, m_nTop);
        else if (m_nBulletStyle == BS_TRIPLE) PaintExtendedBullets(hDC, m_nTop, BS_TRIPLE);
        else if (m_nBulletStyle == BS_COMMENT) PaintExtendedBullets(hDC, m_nTop, BS_COMMENT);
        else if (m_nBulletStyle == BS_GRID) PaintExtendedBullets(hDC, m_nTop, BS_GRID);
        else PaintEmptyBullet(hDC, m_nTop);
}

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

void FolderItem::PaintDiamondBullet(HDC hDC, int nTop)
{
        HPEN hOldPen;
        HPEN hPen;

        if (IsActive()) hPen = CreatePen(PS_SOLID, 1, pSettings->menuHiliteBulletColor);
        else hPen=CreatePen(PS_SOLID, 1, pSettings->menuFrameBulletColor);

        hOldPen = (HPEN) SelectObject(hDC, hPen);

        int x, y, r;

        if (m_nBulletPosition == DT_RIGHT)
        {
                x = GetWidth() - pMenuMaker->m_nBorderWidth - 8;
                if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;
        }
        else
        {
                x = pMenuMaker->m_nBorderWidth + 7;
                if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;
        }
        y = nTop + ((GetHeight()) / 2);

        if (!pSettings->alternativeBullets) r = 3; // larger diamond bullet
        else r = 2; // smaller diamond bullet

        int  fromX, toX, lineY;
        for (fromX = x, toX = x+1, lineY = y-r; lineY <= y+r; lineY++)
        {
                MoveToEx(hDC, fromX, lineY, NULL);
                LineTo (hDC, toX, lineY);
                if (lineY < y) fromX--, toX++;
                else fromX++, toX--;
        }

        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        DeleteObject(hOldPen);
}

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

void FolderItem::PaintTriangleBullet(HDC hDC, int nTop)
{
        HPEN hOldPen;
        HPEN hPen;

        if (IsActive()) hPen = CreatePen(PS_SOLID, 1, pSettings->menuHiliteBulletColor);
        else hPen=CreatePen(PS_SOLID, 1, pSettings->menuFrameBulletColor);

        hOldPen = (HPEN) SelectObject(hDC, hPen);

        int y = nTop + ((GetHeight()) / 2);

        if (!pSettings->alternativeBullets) // Blackbox for Windows "classic" style arrows...
        {
                if (m_nBulletPosition == DT_LEFT) // backward pointing arrow
                {
                        int x = pMenuMaker->m_nBorderWidth + 10;
                        if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x-2, y-2, NULL);
                        LineTo (hDC, x, y-2);
                        MoveToEx(hDC, x-4, y-1, NULL);
                        LineTo (hDC, x, y-1);
                        MoveToEx(hDC, x-6, y, NULL);
                        LineTo (hDC, x, y);
                        MoveToEx(hDC, x-4, y+1, NULL);
                        LineTo (hDC, x, y+1);
                        MoveToEx(hDC, x-2, y+2, NULL);
                        LineTo (hDC, x, y+2);
/*
                        int x = pMenuMaker->m_nBorderWidth + 8;
                        if (pSettings->alternativeMetrics) x += pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x-3, y-1, NULL);
                        LineTo(hDC, x-3, y);
                        MoveToEx(hDC, x-2, y-2, NULL);
                        LineTo(hDC, x-2, y+1);
                        MoveToEx(hDC, x-1, y-3, NULL);
                        LineTo(hDC, x-1, y+2);
                        MoveToEx(hDC, x, y-4, NULL);
                        LineTo(hDC, x, y+3);
*/
                }
                else // forward pointing arrow (default)
                {
                        int x = GetWidth() - pMenuMaker->m_nBorderWidth - 10;
                        if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x, y-2, NULL);
                        LineTo (hDC, x+2, y-2);
                        MoveToEx(hDC, x, y-1, NULL);
                        LineTo (hDC, x+4, y-1);
                        MoveToEx(hDC, x, y, NULL);
                        LineTo (hDC, x+6, y);
                        MoveToEx(hDC, x, y+1, NULL);
                        LineTo (hDC, x+4, y+1);
                        MoveToEx(hDC, x, y+2, NULL);
                        LineTo (hDC, x+2, y+2);
/*
                        int x = GetWidth() - pMenuMaker->m_nBorderWidth - 8;
                        if (pSettings->alternativeMetrics) x -= pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x-1, y-4, NULL);
                        LineTo(hDC, x-1, y+3);
                        MoveToEx(hDC, x, y-3, NULL);
                        LineTo(hDC, x, y+2);
                        MoveToEx(hDC, x+1, y-2, NULL);
                        LineTo(hDC, x+1, y+1);
                        MoveToEx(hDC, x+2, y-1, NULL);
                        LineTo(hDC, x+2, y);
*/
                }
        }
        else // *nix style arrows...
        {
                if (m_nBulletPosition == DT_LEFT) // backward pointing arrow
                {
                        int x = pMenuMaker->m_nBorderWidth + 9;
                        if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x-2, y-1, NULL);
                        LineTo (hDC, x, y-1);
                        MoveToEx(hDC, x-4, y, NULL);
                        LineTo (hDC, x, y);
                        MoveToEx(hDC, x-2, y+1, NULL);
                        LineTo (hDC, x, y+1);
                }
                else // forward pointing arrow (default)
                {
                        int x = GetWidth() - pMenuMaker->m_nBorderWidth - 9;
                        if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;

                        MoveToEx(hDC, x, y-1, NULL);
                        LineTo (hDC, x+2, y-1);
                        MoveToEx(hDC, x, y, NULL);
                        LineTo (hDC, x+4, y);
                        MoveToEx(hDC, x, y+1, NULL);
                        LineTo (hDC, x+2, y+1);
                }
        }

        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        DeleteObject(hOldPen);
}

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

void FolderItem::PaintSquareBullet(HDC hDC, int nTop)
{
        HPEN hOldPen;
        HPEN hPen;

        if (IsActive()) hPen = CreatePen(PS_SOLID, 1, pSettings->menuHiliteBulletColor);
        else hPen=CreatePen(PS_SOLID, 1, pSettings->menuFrameBulletColor);

        hOldPen = (HPEN) SelectObject(hDC, hPen);

        int x;
        if (m_nBulletPosition == DT_RIGHT)
        {
                x = GetWidth() - pMenuMaker->m_nBorderWidth - 7;
                if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;
        }
        else
        {
                x = pMenuMaker->m_nBorderWidth + 7;
                if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;
        }
        int y = nTop + (GetHeight() / 2);

        MoveToEx(hDC, x+2, y+2, NULL);
        LineTo(hDC, x+2, y-3);
        LineTo(hDC, x-3, y-3);
        LineTo(hDC, x-3, y+2);
        LineTo(hDC, x+2, y+2);

        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        DeleteObject(hOldPen);
}

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

void FolderItem::PaintCircleBullet(HDC hDC, int nTop)
{
        HPEN hOldPen;
        HPEN hPen;

        if (IsActive()) hPen = CreatePen(PS_SOLID, 1, pSettings->menuHiliteBulletColor);
        else hPen=CreatePen(PS_SOLID, 1, pSettings->menuFrameBulletColor);

        hOldPen = (HPEN) SelectObject(hDC, hPen);

        int x;
        if (m_nBulletPosition == DT_RIGHT)
        {
                x = GetWidth() - pMenuMaker->m_nBorderWidth - 7;
                if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;
        }
        else
        {
                x = pMenuMaker->m_nBorderWidth + 7;
                if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;
        }

        int y = nTop + (GetHeight() / 2);

        if (!pSettings->alternativeBullets) Arc(hDC, x-4, y-3, x+3, y+4, x-1, y-3, x-1, y-3);
        else
        {
                MoveToEx(hDC, x-2, y-3, NULL);
                LineTo (hDC, x+2, y-3);
                MoveToEx(hDC, x-3, y-2, NULL);
                LineTo (hDC, x-3, y+2);
                MoveToEx(hDC, x+2, y-2, NULL);
                LineTo (hDC, x+2, y+2);
                MoveToEx(hDC, x-2, y+2, NULL);
                LineTo (hDC, x+2, y+2);
        }

        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        DeleteObject(hOldPen);
}

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

void FolderItem::PaintExtendedBullets(HDC hDC, int nTop, int type)
{
        HPEN hOldPen;
        HPEN hPen;

        (IsActive()) ? hPen = CreatePen(PS_SOLID, 1, pSettings->menuHiliteBulletColor) : hPen=CreatePen(PS_SOLID, 1, pSettings->menuFrameBulletColor);

        hOldPen = (HPEN) SelectObject(hDC, hPen);

        int x;
        if (m_nBulletPosition == DT_RIGHT)
        {
                x = GetWidth() - pMenuMaker->m_nBorderWidth - 7;
                if (!pSettings->slimlineMetrics) x -= pSettings->MenuFrame->marginWidth;
        }
        else
        {
                x = pMenuMaker->m_nBorderWidth + 7;
                if (!pSettings->slimlineMetrics) x += pSettings->MenuFrame->marginWidth;
        }
        int y = nTop + (GetHeight() / 2);

        if (type == BS_TRIPLE)
        {
                if (IsActive()) // Use horizontal lines...
                {
                        MoveToEx(hDC, x+2, y-2, NULL);
                        LineTo(hDC, x-3, y-2);
                        MoveToEx(hDC, x+2, y, NULL);
                        LineTo(hDC, x-3, y);
                        MoveToEx(hDC, x+2, y+2, NULL);
                        LineTo(hDC, x-3, y+2);
                }
                else // Use vertical lines...
                {
                        MoveToEx(hDC, x+2, y+2, NULL);
                        LineTo(hDC, x+2, y-3);
                        MoveToEx(hDC, x, y+2, NULL);
                        LineTo(hDC, x, y-3);
                        MoveToEx(hDC, x-2, y+2, NULL);
                        LineTo(hDC, x-2, y-3);
                }
        }
        else if (type == BS_COMMENT)
        {
//              MoveToEx(hDC, x-2, y-3, NULL);
//              LineTo(hDC, x-1, y-3);
//              MoveToEx(hDC, x, y-3, NULL);
//              LineTo(hDC, x-3, y);
//              MoveToEx(hDC, x+2, y-3, NULL);
//              LineTo(hDC, x-3, y+2);
//              MoveToEx(hDC, x+2, y-1, NULL);
//              LineTo(hDC, x-1, y+2);
//              MoveToEx(hDC, x+2, y+1, NULL);
//              LineTo(hDC, x+1, y+2);

                MoveToEx(hDC, x, y-3, NULL);
                LineTo(hDC, x-4, y+1);
                MoveToEx(hDC, x+2, y-1, NULL);
                LineTo(hDC, x-2, y+3);
        }
        else if (type == BS_GRID)
        {
                MoveToEx(hDC, x+1, y-2, NULL);
                LineTo(hDC, x-3, y-2);
                MoveToEx(hDC, x+1, y, NULL);
                LineTo(hDC, x-3, y);
                MoveToEx(hDC, x+1, y+2, NULL);
                LineTo(hDC, x-3, y+2);

                MoveToEx(hDC, x+2, y+2, NULL);
                LineTo(hDC, x+2, y-3);
                MoveToEx(hDC, x, y+2, NULL);
                LineTo(hDC, x, y-3);
                MoveToEx(hDC, x-2, y+2, NULL);
                LineTo(hDC, x-2, y-3);
        }

        SelectObject(hDC, hOldPen);
        DeleteObject(hPen);
        DeleteObject(hOldPen);
}

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

void FolderItem::PaintEmptyBullet(HDC hDC, int nTop)
{
        // Nothing here... :)
}

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

void FolderItem::GetTitleRect(RECT* r)
{
        TitleItem::GetTitleRect(r);
}

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

void FolderItem::Attached(Menu* pMenu)
{
        TitleItem::Attached(pMenu);     

        m_pParent->AddChild(m_pSubMenu);
        m_pSubMenu->SetParent(m_pParent);
}

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

void FolderItem::Invoke()
{
        Active(true);
}

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

bool FolderItem::Active(bool bActivate)
{
        bool result = TitleItem::Active(bActivate);

        if (bActivate)
        {
                if (!IsWindowVisible(m_pSubMenu->GetWindow()) && m_nTimerId == 0)
                {
                        m_nTimerId = (UINT)this;
                        SetTimer(GetWindow(), m_nTimerId, pSettings->submenuDelay, NULL);
                }
        }
        else
        {       
                if (m_nTimerId != 0) KillTimer(GetWindow(), m_nTimerId);
                m_nTimerId = 0;

                if (m_pSubMenu != NULL)
                {
                        if(IsWindowVisible(m_pSubMenu->GetWindow()))
                                m_pSubMenu->Hide(HIDE_CHILDREN);
                }
        }

        return result;
}

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

void FolderItem::Timer(int nTimer)
{
        if ((UINT)nTimer == m_nTimerId)
        {
                ShowSubMenu();
                KillTimer(GetWindow(), m_nTimerId);
                m_nTimerId = 0;
        }
}

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

void FolderItem::ShowSubMenu()
{
        RECT r;
        RECT s;
        RECT screen;
        RECT rParent = {0,0,0,0};
        Menu* pParent;
        int x, y, test_x;

        // This window 
        GetWindowRect(GetWindow(), &r);

        // Subfolder window
        GetWindowRect(m_pSubMenu->GetWindow(), &s);

        pParent = m_pParent->GetParent();
        if (pParent) GetWindowRect(pParent->GetWindow(), &rParent);

        x = r.right - pMenuMaker->m_nBorderWidth;
        y = r.top + m_nTop - pMenuMaker->m_nTitleHeight;

        //====================
/*
        // Get width and height of screen
        int screenx = GetSystemMetrics(SM_CXSCREEN);
        int screeny = GetSystemMetrics(SM_CYSCREEN);

        if(y + (s.bottom - s.top) > screeny)
                y = screeny - (s.bottom - s.top);
*/
        POINT pt = {x ,y};
        HMONITOR hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
        MONITORINFO mi;

        mi.cbSize = sizeof(mi);

        if (GetMonitorInfo(hMon, &mi))
        {
                screen.left = mi.rcMonitor.left;
                screen.top = mi.rcMonitor.top;
                screen.right = mi.rcMonitor.right;
                screen.bottom = mi.rcMonitor.bottom;
        }
        else
        {
                screen.left = 0;
                screen.top = 0;

                if (pSettings->usingWin2kXP)
                {
                        screen.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
                        screen.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
                }
                else
                {
                        screen.right = GetSystemMetrics(SM_CXSCREEN);
                        screen.bottom = GetSystemMetrics(SM_CYSCREEN);
                }
        }

//      if (y + (s.bottom - s.top) > screen.bottom)
//              y = screen.bottom - (s.bottom - s.top);
        while (y + (s.bottom - s.top) > screen.bottom)
                y = y - pMenuMaker->m_nSubmenuHeight;

        test_x = r.left - (s.right - s.left) + pMenuMaker->m_nBorderWidth;
        if ((pParent && ((rParent.left > r.left) && (test_x >= screen.left)) && !m_pParent->IsPinned()) || (x + (s.right - s.left) > screen.right))
                // If my window is to the left of my parent menu
                x = test_x;
/*
        //The m_pParent->HasMoved() check solves BUG(s) 669084 & 711111
        if (((pParent && (rParent.left > r.left)) || x + (s.right - s.left) > screenx) && !m_pParent->HasMoved())
                // If my window is to the left of my parent menu
                x = r.left - (s.right - s.left) + m_nOverlapX;
*/
        //====================

        // Keep focus on this folder.. 
        SetForegroundWindow(GetWindow()); 

        m_pSubMenu->Show(x, y);
        SendMessage(GetBBWnd(), BB_SUBMENU, 0, 0);
}

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





syntax highlighting by

w e b c p p
web c plus plus