//this file is part of notepad++
//Copyright (C)2003 Don HO ( donho@altern.org )
//
//This program is free software; you can redistribute it and/or
//modify it under the terms of the GNU General Public License
//as published by the Free Software Foundation; either
//version 2 of the License, or (at your option) any later version.
//
//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.
//
//You should have received a copy of the GNU General Public License
//along with this program; if not, write to the Free Software
//Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

#include "SplitterContainer.h"
#include "SysMsg.h"


bool SplitterContainer::_isRegistered = false;

void SplitterContainer::create(Window *pWin0, Window *pWin1, int splitterSize,
                               SplitterMode mode, int ratio, bool isVertical)
{
	//Window::init(hInst, parent);
	_pWin0 = pWin0;
	_pWin1 = pWin1;
	_splitterSize = splitterSize;
	_splitterMode = mode;
	_ratio = ratio;
	_dwSplitterStyle |= isVertical?SV_VERTICAL:SV_HORIZONTAL;
    if (_splitterMode != DYNAMIC)
	{
        _dwSplitterStyle |= SV_FIXED;
		_dwSplitterStyle &= ~SV_RESIZEWTHPERCNT;
	}
	if (!_isRegistered)
	{
		WNDCLASS splitterContainerClass;

		splitterContainerClass.style = 0;
		splitterContainerClass.lpfnWndProc = staticWinProc;
		splitterContainerClass.cbClsExtra = 0;
		splitterContainerClass.cbWndExtra = 0;
		splitterContainerClass.hInstance = _hInst;
		splitterContainerClass.hIcon = NULL;
		splitterContainerClass.hCursor = NULL;

		// hbrBackground must be NULL,
		// otherwise this window will hide some parts of 2 windows
		splitterContainerClass.hbrBackground = NULL; 
		splitterContainerClass.lpszMenuName = NULL;
		splitterContainerClass.lpszClassName = SPC_CLASS_NAME;//_className;

		if (!::RegisterClass(&splitterContainerClass))
		{
			systemMessage("System Err");
			throw int(98);
		}
		_isRegistered = true;
	}

	_hSelf = ::CreateWindowEx(
					0,
					SPC_CLASS_NAME,
					"a koi sert?",
					WS_CHILD |  WS_CLIPCHILDREN,
					CW_USEDEFAULT, CW_USEDEFAULT,
					CW_USEDEFAULT, CW_USEDEFAULT,
					_hParent,
					NULL,
					_hInst,
					(LPVOID)this);

	if (!_hSelf)
	{
		systemMessage("System Err");
		throw int(777);
	}
}

void SplitterContainer::rotateTo(DIRECTION direction) 
{
	bool doSwitchWindow = false;
	if (_dwSplitterStyle & SV_VERTICAL)
	{
		_dwSplitterStyle ^= SV_VERTICAL;
		_dwSplitterStyle |= SV_HORIZONTAL;
		doSwitchWindow = (direction == LEFT);
	}
	else
	{
		_dwSplitterStyle ^= SV_HORIZONTAL;
		_dwSplitterStyle |= SV_VERTICAL;
		doSwitchWindow = (direction == RIGHT);
	}
	if (doSwitchWindow)
	{
		Window *tmp = _pWin0;
		_pWin0 = _pWin1;
		_pWin1 = tmp;
	}
	_splitter.rotate();

}

LRESULT CALLBACK SplitterContainer::staticWinProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	SplitterContainer *pSplitterContainer = NULL;
	switch (message)
	{	
		case WM_NCCREATE :
			pSplitterContainer = (SplitterContainer *)(((LPCREATESTRUCT)lParam)->lpCreateParams);
			pSplitterContainer->_hSelf = hwnd;
			::SetWindowLong(hwnd, GWL_USERDATA, reinterpret_cast<LONG>(pSplitterContainer));
			return TRUE;

		default :
			pSplitterContainer = (SplitterContainer *)::GetWindowLong(hwnd, GWL_USERDATA);
			if (!pSplitterContainer)
				return ::DefWindowProc(hwnd, message, wParam, lParam);
			return pSplitterContainer->runProc(message, wParam, lParam);
	}
}

LRESULT SplitterContainer::runProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
		case WM_CREATE :
			_splitter.init(_hInst, _hSelf, _splitterSize, _ratio, _dwSplitterStyle);
			return TRUE;
		
		case WM_COMMAND :
		{
			switch (LOWORD(wParam)) 
			{
				case ROTATION_A_GAUCHE:
					rotateTo(LEFT);
					return TRUE;
				case ROTATION_A_DROITE:
					rotateTo(RIGHT);
					return TRUE;
			}
			return TRUE;
		}
		case WM_RESIZE_CONTAINER :
		{
			RECT rc0, rc1;
			getClientRect(rc0);

			rc1.top = rc0.top += _y;
			rc1.bottom = rc0.bottom;
			rc1.left = rc0.left += _x;
			rc1.right = rc0.right;

			if (_dwSplitterStyle & SV_VERTICAL)
			{
				if (wParam != 0)
				{
					rc0.right = int(wParam);

					rc1.left = int(wParam) + _x + _splitter.getPhisicalSize();
					rc1.right = rc1.right - rc1.left + _x;
				}
			}
			else //SV_HORIZONTAL
			{
				if (lParam != 0)
				{
					rc0.bottom = int(lParam); 

					rc1.top   = int(lParam) + _y + _splitter.getPhisicalSize();
					rc1.bottom = rc1.bottom - rc1.top + _y;
				}
			}
			_pWin0->reSizeTo(rc0);
			_pWin1->reSizeTo(rc1);

			return TRUE;
		}
		
		case WM_DOPOPUPMENU :
		{
			if ((_splitterMode != LEFT_FIX) && (_splitterMode != RIGHT_FIX) )
			{
				POINT p;
				::GetCursorPos(&p);
				
				if (!_hPopupMenu)
				{
					POINT p;
					::GetCursorPos(&p);
					_hPopupMenu = ::CreatePopupMenu();
					::InsertMenu(_hPopupMenu, 1, MF_BYPOSITION, ROTATION_A_GAUCHE, "Rotate to left");
					::InsertMenu(_hPopupMenu, 0, MF_BYPOSITION, ROTATION_A_DROITE, "Rotate to right");
				}
				
				::TrackPopupMenu(_hPopupMenu, TPM_LEFTALIGN, p.x, p.y, 0, _hSelf, NULL);
			}
			return TRUE;
		}

		case WM_GETSPLITTER_X :
        {
            if (_splitterMode == LEFT_FIX)
                return MAKELONG(_pWin0->getWidth(), LEFT_FIX);
            else if (_splitterMode == RIGHT_FIX)
            {
                int x = getWidth()-_pWin1->getWidth();
                if (x < 0)
                    x = 0;
                return MAKELONG(x, RIGHT_FIX);
            }
            else
			    return MAKELONG(0, DYNAMIC);
         
        }

		case WM_GETSPLITTER_Y :
        {
            if (_splitterMode == LEFT_FIX)
                return MAKELONG(_pWin0->getHeight(), LEFT_FIX);
            else if (_splitterMode == RIGHT_FIX)
            {
                int y = getHeight()-_pWin1->getHeight();
                if (y < 0)
                    y = 0;
                return MAKELONG(y, RIGHT_FIX);
            }
            else
			    return MAKELONG(0, DYNAMIC);
        }

		default :
			return ::DefWindowProc(_hSelf, message, wParam, lParam);
	}
}
