/*
Program childFrameCaml: Graphical User Interface
for interactive use of Caml-Light and Ocaml.
Copyright (C) 2005-2015 Jean Mouric 35700 Rennes France
email: jean.mouric@orange.fr

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 3 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, see <http://www.gnu.org/licenses/>. 
*/

// File CSplitter.cpp

#include "CChildFrame.h"
#include "CSplitter.h"

CSplitter::CSplitter(CChildFrame* cfr, CRichEdit* re1, CRichEdit* re2, int splitterViewMode,
                     int xSplit, int xDim, int ySplit, int yDim, bool verticalSplitBar) : CSplitterBase(cfr)
{
	childFrame = cfr;
	richEdit1 = re1;
	richEdit2 = re2;
	int width, height;
	cfr->getClientSize(width, height);
	this->xDim = width;
	xPos0 = this->xSplit = xAdjust(mulDiv(this->xDim, xSplit, xDim));
	this->yDim = height;
	yPos0 = this->ySplit = yAdjust(mulDiv(this->yDim, ySplit, yDim));
	verticalBar = verticalSplitBar;
	viewMode = splitterViewMode;
	xMove = yMove = false;
	resize();
}

CSplitter::~CSplitter()
{
}

int CSplitter::xAdjust(int xSplit)
{
	int width, height;
	childFrame->getClientSize(width, height);
	if(xSplit > width - MINSIZE)
	{
		xSplit = width - MINSIZE;
	}
	else if(xSplit < MINSIZE)
	{
		xSplit = MINSIZE;
	}
	return xSplit;
}
int CSplitter::yAdjust(int ySplit)
{
	int width, height;
	childFrame->getClientSize(width, height);
	if(ySplit > height - MINSIZE)
	{
		ySplit = height - MINSIZE;
	}
	else if(ySplit < MINSIZE)
	{
		ySplit = MINSIZE;
	}
	return ySplit;
}
void CSplitter::zoom()
{
	int width, height;
	childFrame->getClientSize(width, height);
	int xDimNew = width;
	if (xDimNew != 0)
	{
		xSplit = xAdjust(mulDiv(xSplit, xDimNew, xDim));
		resize();
		xPos0 = mulDiv(xPos0, xDimNew, xDim);
		xDim = xDimNew;
	}
	int yDimNew = height;
	if (yDimNew != 0)
	{
		ySplit = yAdjust(mulDiv(ySplit, yDimNew, yDim));
		resize();
		yPos0 = mulDiv(yPos0, yDimNew, yDim);
		yDim = yDimNew;
	}
}
void CSplitter::resize()
{
	childFrame->getClientSize(width, height);
	if (verticalBar)
	{
		int xSplit1 = xSplit;
		if (viewMode == VIEW_INPUTONLY)
			xSplit1 = width - MINSIZE;
		else if (viewMode == VIEW_OUTPUTONLY)
			xSplit1 = MINSIZE;
		richEdit1->move(0, 0, xSplit1 - HALFBARWIDTH, height);
		richEdit2->move(xSplit1 + HALFBARWIDTH, 0, width - xSplit1 - HALFBARWIDTH, height);
        moveVerticalSash(xSplit1);
	}
	else
	{
		int ySplit1 = ySplit;
		if (viewMode == VIEW_INPUTONLY)
			ySplit1 = height - MINSIZE;
		else if (viewMode == VIEW_OUTPUTONLY)
			ySplit1 = MINSIZE;
		richEdit1->move(0, 0, width, ySplit1 - HALFBARWIDTH);
		richEdit2->move(0, ySplit1 + HALFBARWIDTH,  width, height - ySplit1 - HALFBARWIDTH);
        moveHorizontalSash(ySplit1);
	}
}
void CSplitter::setViewMode(int mode)
{
	viewMode = mode;
	resize();
}
bool CSplitter::movingHorizontally()
{
	return verticalBar && ((viewMode == VIEW_BOTH && (xPos >= xSplit - HALFBARWIDTH) && (xPos <= xSplit + HALFBARWIDTH)) ||
		(viewMode == VIEW_INPUTONLY && (xPos >= width - HALFBARWIDTH - MINSIZE)) || (viewMode == VIEW_OUTPUTONLY && (xPos < MINSIZE + HALFBARWIDTH)));
}
bool CSplitter::movingVertically()
{
	return !verticalBar && ((viewMode == VIEW_BOTH && (yPos >= ySplit - HALFBARWIDTH) && (yPos <= ySplit + HALFBARWIDTH)) ||
		(viewMode == VIEW_INPUTONLY && (yPos >= height - HALFBARWIDTH - MINSIZE)) || (viewMode == VIEW_OUTPUTONLY && (yPos < MINSIZE + HALFBARWIDTH)));
}
void CSplitter::onLeftButtonDown(int posx, int posy)
{
	xPos = posx;
	yPos = posy;
	xMove = movingHorizontally();    
	yMove = movingVertically();
	if(xMove)
	{
		childFrame->setCapture();
		if (viewMode == VIEW_BOTH)
			xSplit = xPos0 = xPos;
		else if (viewMode == VIEW_INPUTONLY)
			xSplit = xPos0 = width - MINSIZE;
		else 
			xSplit = xPos0 = MINSIZE;
		viewMode = VIEW_BOTH;
		childFrame->setCursor(EAST_WEST);
		if (!liveSplit)
			childFrame->drawFocusRect(xSplit - HALFBARWIDTH, 0, xSplit + HALFBARWIDTH, height);
	}
	else if(yMove)
	{
		childFrame->setCapture();
		if (viewMode == VIEW_BOTH)
			ySplit = yPos0 = yPos;
		else if (viewMode == VIEW_INPUTONLY)
			ySplit = yPos0 = height - MINSIZE;
		else 
			ySplit = yPos0 = MINSIZE;
		viewMode = VIEW_BOTH;
		childFrame->setCursor(SOUTH_NORTH);
		if (!liveSplit)
			childFrame->drawFocusRect(0, ySplit - HALFBARWIDTH, width,  ySplit + HALFBARWIDTH);
	}
} 
void CSplitter::onLeftButtonUp()
{
	if (xMove)
	{
		if (!liveSplit)
		{
			childFrame->drawFocusRect(xSplit - HALFBARWIDTH, 0, xSplit + HALFBARWIDTH, height);
		}
		if (xPos != xPos0)
			resize();
	}
	else if (yMove)
	{
		if (!liveSplit)
		{
			childFrame->drawFocusRect(0, ySplit - HALFBARWIDTH, width,  ySplit + HALFBARWIDTH);
		}
		if (yPos != yPos0)
			resize();
	}
	childFrame->releaseCapture();
	xMove = yMove = false;
	richEdit1->updateView();
	richEdit2->updateView();
} 
void CSplitter::onMouseMove(int posx, int posy, bool mouseDown)
{

	xPos = xAdjust(posx);
	yPos = yAdjust(posy);
	if (mouseDown)
	{
		if (xMove)
		{
			if (!liveSplit)
			{
				childFrame->drawFocusRect(xSplit - HALFBARWIDTH, 0, xSplit + HALFBARWIDTH, height);
				childFrame->drawFocusRect(xPos - HALFBARWIDTH, 0, xPos + HALFBARWIDTH, height);
			}
			xSplit = xPos;
		}
		else if (yMove)
		{
			if (!liveSplit)
			{
				childFrame->drawFocusRect(0, ySplit - HALFBARWIDTH, width,  ySplit + HALFBARWIDTH);
				childFrame->drawFocusRect(0, yPos - HALFBARWIDTH, width,  yPos + HALFBARWIDTH);
			}
			ySplit = yPos;
		}
		if (liveSplit) resize();
	}
	if (movingHorizontally())
	{
		childFrame->setCursor(EAST_WEST);
	}
	else if (movingVertically())
	{
		childFrame->setCursor(SOUTH_NORTH);
	}
	else
	{
		childFrame->setCursor(ARROW);
	}
	richEdit1->updateCursor();
	richEdit2->updateCursor();
}
void CSplitter::setVertical(bool b)
{
	verticalBar = b;
	resize();
}
