/***************************************************************************
 *   Copyright (C) 2005 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "layertool.h"
//Added by qt3to4:
#include <QResizeEvent>
#include <QBoxLayout>
#include <QPainter>
#include <QMatrix>
#include <QStyle>
#include <QStyleOption>
#include <QShortcut>
#include "general/setup.h"
#include <QHash>
#include <QString>
#include "dialog/helpwindow.h"

layerTool::layerTool(QWidget *parent,const QString & title)
 : QDockWidget(title,parent)
{
 initLayers=0;
 leftLabel=10;
 topRowOffset=0;
 setObjectName(title);
 setFeatures(QDockWidget::AllDockWidgetFeatures);
 setWindowTitle (tr("Layer"));
 //setWindowTitle (tr(""));

  layersWidget=new layerWidget(this,parent);
  initUsedLayers();
  scrollBar= new QScrollBar(Qt::Vertical,layersWidget);
  scrollBar->hide();
  for (int i=initLayers;i<layersMax;i++){
	button[i]=button[0];
	}
  /*for (int i=0;i<layersMax;i++){
	button[i]=new layerbutton(i,this);
	button[i]->setGeometry(i%3*21,i/3*21,20,20); 
	//if (i>=layers::displayedLayers) button[i]->hide();
	//button[i]->setGeometry(1,1,20,20); 
       connect(button[i],SIGNAL(aktiveLayer(int)),parent,SLOT(aktiveLayerChange(int )));
       connect(button[i],SIGNAL(visibleChange()),parent,SLOT(paint()));  
       connect(button[i],SIGNAL(updateAllLayerbutton()),parent,SLOT(updateLayerbutton()));
      // connect(button[i],SIGNAL(changed(int)),parent,SLOT(updateLayerMenu(int)));	
       connect(button[i],SIGNAL(updateSetup()),parent,SLOT(updateSetupLayerbutton()));	
       connect(button[i],SIGNAL(macroAdd(QString)),parent,SLOT(macroAdd(QString)));	
  }*/
  //layersWidget->setMinimumSize(21,41);
  layersWidget->setGeometry(0,20,100,100);
  setWidget(layersWidget);
  setMinimumSize(41,61);
  setMaximumSize(300,800);
  setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
  setFeatures(QDockWidget::DockWidgetClosable|QDockWidget::DockWidgetMovable|QDockWidget::DockWidgetFloatable);
  //installEventFilter(this);
  oneLayerPerRow=false;
  sorting=0;
  connect(scrollBar,SIGNAL(valueChanged(int)),this,SLOT(scrolled(int)));
  connect(scrollBar,SIGNAL(sliderMoved(int)),this,SLOT(scrolled(int)));
}

void layerTool::initUsedLayers(){
  for (int i=initLayers;i<layers::displayedLayers;i++){
	button[i]=new layerbutton(i,this);
	button[i]->setGeometry(i%3*21,i/3*21,20,20); 
	//if (i>=layers::displayedLayers) button[i]->hide();
	//button[i]->setGeometry(1,1,20,20); 
       connect(button[i],SIGNAL(aktiveLayer(int)),parent(),SLOT(aktiveLayerChange(int )));
       connect(button[i],SIGNAL(visibleChange()),parent(),SLOT(paint()));  
       connect(button[i],SIGNAL(updateAllLayerbutton()),parent(),SLOT(updateLayerbutton()));
      // connect(button[i],SIGNAL(changed(int)),parent,SLOT(updateLayerMenu(int)));	
       connect(button[i],SIGNAL(updateSetup()),parent(),SLOT(updateSetupLayerbutton()));	
       connect(button[i],SIGNAL(macroAdd(QString)),parent(),SLOT(macroAdd(QString)));
	if (initLayers!=0){
		button[i]->setToolTip(layers::num[i].name);
		button[i]->show();
		button[i]->changeSetup();	
	}
  }

initLayers=layers::displayedLayers;
}


layerTool::~layerTool(){
 delete scrollBar;
}

void layerTool::placeButtons(){
// printf("place\n");
resizeRuning=true;
setUpdatesEnabled(false);
if (initLayers<layers::displayedLayers) initUsedLayers();
  //printf("resize %d %d\n",width(),height());
  //printf("minimum %d %d\n",layersWidget->minimumSize().width(),layersWidget->minimumSize().height());
  //printf("actuel %d %d\n",layersWidget->width(),layersWidget->height());
  //QStyleOption option;
  //option.initFrom(this);
  //title=option.rect.height();
  //printf("title 1 %d\n",title);
  title=layersWidget->frameGeometry().height()-layersWidget->geometry().height()+20;
  title+=style()->pixelMetric(QStyle::PM_DockWidgetTitleMargin,NULL,this);
 //printf("title %d\n",title);
  cols=(layersWidget->width()-leftLabel)/21;
  rows=(layersWidget->height()-title)/21;
  for (int i=0;i<initLayers;i++) button[i]->setGeometry(layersWidget->width(),1,0,0);

  colDif=(double(layersWidget->width()-leftLabel)/cols);
  rowDif=(double(layersWidget->height())/rows);
  double rDif=rowDif-21;
  double cDif=colDif-21;
  int num=-1;
  oneLayerPerRow=false;
  int count=0;
  while (num<layers::displayedLayers) {
    num++;
    if (layers::num[num].use==true) count++;
  }
  num=-1;
  if (((count<=rows)||(setup::layerDockStyle==2))&&(setup::layerDockStyle!=1)){ //list display
    // one row per layer
     if (count<=rows) {
       scrollBar->hide();
       topRowOffset=0;
     }
     else {
       scrollBar->setGeometry(layersWidget->width()-12,4,12,layersWidget->height()-5);
       scrollBar->setPageStep(rows);
       scrollBar->setTracking(true);
       scrollBar->setMaximum(count-rows);
       scrollBar->setEnabled(true);
       scrollBar->show();
     }
     oneLayerPerRow=true;
     for (int k=0;k<layersMax;k++) rowStart[k]= -1;
     if (sorting==0){
       int pos=0;num=0;
       while (num<layers::displayedLayers) {
       if (layers::num[num].use==true) {rowStart[pos]=num; pos++;}
       num++;
       }
     }else
     {
       QHash<QString,int> layernames;
       QStringList list;
       for (int k=0;k<layers::displayedLayers;k++){
	 if (layers::num[k].use==true){layernames.insert(layers::num[k].name,k);list<<layers::num[k].name;}
       }
       list.sort();
       for (int k=0;k<list.size();k++) rowStart[k]=layernames.value(list.at(k));
     }
     for (int k=0;k<rows;k++){
		int lay=rowStart[k+topRowOffset];
		rowStart[k]=lay;
		if (lay>=0)
		{
		button[lay]->setGeometry(1+leftLabel,(int)(rowDif*k)+title,(int)(20+cDif),(int)(20+rDif));
		}
	}
  }
  else { // block display
    for (int k=0;k<rows;k++)
      for (int i=0;i<cols;i++) {
	num++;
	while ((num<layers::displayedLayers)&&(layers::num[num].use==false)) num++;
	if (i==0){rowStart[k]=num;}
        if (num<layers::displayedLayers)
	      button[num]->setGeometry((int)(colDif*i)+1+leftLabel,(int)(rowDif*k)+title,(int)(20+cDif),(int)(20+rDif));
     }
     scrollBar->hide();topRowOffset=0;
  }
  setUpdatesEnabled(true);
  resizeRuning=false;
}

void layerTool::resizeEvent ( QResizeEvent * e ){
  //printf("resize %d %d\n",e->size().width(),e->size().height());
  QDockWidget::resizeEvent(e);installEventFilter(this);
  placeButtons();
  repaint();
}

void layerTool::paintEvent ( QPaintEvent * event ){
QDockWidget::paintEvent (event );
if (resizeRuning) return;
QPainter p(this);
QMatrix m(0,-1,1,0,0,0);
QMatrix mnormal(1,0,0,1,0,0);
for (int i=0; i<rows;i++)
	if (rowStart[i]>=0){
	QString s;
	s.setNum(rowStart[i]);
	p.setMatrix(m);
	QRect r(-(int)(rowDif*(i+1))-title,0,(int)rowDif,leftLabel);
	QFont f;
        f.setPixelSize(9);
        p.setFont(f);
	p.drawText(r,Qt::AlignHCenter,s);
	if (oneLayerPerRow)
	if ((rowStart[i]<layers::displayedLayers)&&(rowStart[i]>=0)){
		s=layers::num[rowStart[i]].name;
		p.setMatrix(mnormal);
		r= QRect((int)(colDif)+leftLabel, (int)(rowDif*(i))+title, layersWidget->width()-leftLabel-(int)(colDif),(int)rowDif);
		f.setPixelSize(11);
		p.setFont(f);
		p.drawText(r,Qt::AlignVCenter,s);}
  }
}

void layerTool::updateAllButtons(){
  int i;
  if (initLayers<layers::displayedLayers) initUsedLayers();
  for (i=0;i<layers::displayedLayers;i++){button[i]->changeSetup();}
  placeButtons();
  repaint();
}

void layerTool::layerActive(){
layerShortkeyMode=1;
setFocus();
}
void layerTool::layerVisibleToggle(){
layerShortkeyMode=2;
setFocus();
}

void layerTool::layerHideOther(){
layerShortkeyMode=3;
setFocus();
}
void layerTool::layerShowAll(){
button[1]->showAllLayer();
}

void layerTool::focusInEvent ( QFocusEvent * event ){
  if (initLayers<layers::displayedLayers) initUsedLayers();
  for (int i=0;i<layers::displayedLayers;i++){
  button[i]->shortkey=true;
  }
  update();
  grabKeyboard ();
  QWidget::focusInEvent ( event );
}

void layerTool::focusOutEvent ( QFocusEvent * event ){
  if (initLayers<layers::displayedLayers) initUsedLayers();
  for (int i=0;i<layers::displayedLayers;i++){
  button[i]->shortkey=false;;
  }
  update();
  releaseKeyboard ();
  QWidget::focusInEvent ( event );
}


void layerTool::wheelEvent(QWheelEvent *e){
       //   printf("wheelEvent %d\n",e->delta());
       if (!scrollBar->isVisible()) return;
       if (e->delta()>0)
  topRowOffset-=1;
  else topRowOffset+=1;
  if (topRowOffset<0) topRowOffset=0;
  if (topRowOffset>initLayers-rows) topRowOffset=initLayers-rows;
  scrollBar->setValue(topRowOffset);
  placeButtons();
  update();
     //       printf("wheelEvent end\n");
}

void layerTool::mouseDoubleClickEvent ( QMouseEvent * e ){
  if (e->button()==Qt::LeftButton){ 
	int pos=e->pos().x();
	if (pos<leftLabel) if (sorting!=0) {sorting=0; placeButtons();}
	if (pos>colDif+leftLabel) if (sorting!=1) {sorting=1; placeButtons();}
	
	}
}

void layerTool::scrolled(int val){
  if (val!=topRowOffset)
    {
    //printf("%d %d\n",val,topRowOffset);
    topRowOffset=val;
    placeButtons();
    update();
  }
  
}

bool layerTool::eventFilter(QObject *obj, QEvent *e){
     if (e->type() == QEvent::ShortcutOverride) {
			if (hasFocus()) {
				e->accept();
				return false;
			} }
     if (e->type() == QEvent::KeyPress) {
                QKeyEvent *keyEvent = static_cast<QKeyEvent *>(e);
		if (hasFocus()) {}
		int found=-1;
		/*QKeySequence g(keyEvent->modifiers ()+keyEvent->key());
		QKeySequence h(Qt::ShiftModifier+Qt::Key_2);
		QShortcut sc(h,this);
 		if (h.matches(g)==QKeySequence::ExactMatch)printf("Shift+2");
		printf("-> %s %s %s\n ",h.toString().toAscii().data(),g.toString().toAscii().data(),sc.key().toString().toAscii().data());
		//printf("%s %d %d %d\n",keyEvent->text().toAscii().data(),keyEvent->key(),(int)keyEvent->modifiers (),(int)keyEvent-> nativeScanCode  ());*/
		if (initLayers<layers::displayedLayers) initUsedLayers();
		for (int i=0; i<layers::displayedLayers;i++){
			if (layers::num[i].use)
			if (layers::num[i].getShortkeyModifiers()==keyEvent->modifiers ()&&(keyEvent->key()==layers::num[i].getShortkeyKey())){
				found=i;
				i=layersMax;
			}
		}
		if (found>=0) {
			//printf("found %d\n",found);
			if (layerShortkeyMode==1) {
			    	button[found]->makeLayerAktive();
				emit shortkeyFinished();
				return true;
				}
			if (layerShortkeyMode==2) {
			    	if (!layers::num[found].visible) button[found]->showLayer();
  				else button[found]->hideLayer();
				return true;
				}
			if (layerShortkeyMode==3) {
			    	button[found]->hideOtherLayer();
				return true;
				}
			}
		if ((keyEvent->key()==Qt::Key_Return)|| (keyEvent->key()==Qt::Key_Enter)) {
			emit shortkeyFinished();
			return true;
			}
                if (keyEvent->key()==Qt::Key_Escape) {
			emit shortkeyFinished();
			return false;
		}
		return true;
		}
return QDockWidget::eventFilter(obj, e);
}


void layerTool::contextMenuEvent ( QContextMenuEvent * event) {
  if (QApplication::keyboardModifiers ()!=Qt::NoModifier) {event->ignore();return;}
  //printf("content menu requested\n");
#ifdef FULL_VERSION
QMenu menu;
if (oneLayerPerRow) {
  if (sorting !=0) menu.addAction(helpWindow::getIcon(layer123Help),helpWindow::getMenuname(layer123Help),this,SLOT(layerSortNumber()));
  else menu.addAction(helpWindow::getIcon(layerABCHelp),helpWindow::getMenuname(layerABCHelp),this,SLOT(layerSortName()));
menu.addAction(helpWindow::getIcon(layerBlockHelp),helpWindow::getMenuname(layerBlockHelp),this,SLOT(layersAsBlock()));
}
else menu.addAction(helpWindow::getIcon(layerListHelp),helpWindow::getMenuname(layerListHelp),this,SLOT(layersAsList()));
menu.addSeparator();
menu.addAction(helpWindow::getIcon(hideUnusedLayersHelp),helpWindow::getMenuname(hideUnusedLayersHelp),parent(),SLOT(hideUnusedLayers()));
menu.addAction(helpWindow::getIcon(disableUnusedLayersHelp),helpWindow::getMenuname(disableUnusedLayersHelp),parent(),SLOT(disableUnusedLayers()));
menu.addAction(helpWindow::getIcon(enableAllLayersHelp),helpWindow::getMenuname(enableAllLayersHelp),parent(),SLOT(enableAllLayer()));
menu.addAction(helpWindow::getIcon(hideCurUnusedLayersHelp),helpWindow::getMenuname(hideCurUnusedLayersHelp),parent(),SLOT(hideCurrentUnusedLayers()));
menu.addSeparator();
// menu.addAction(helpWindow::getIcon(layerManagerHelp),helpWindow::getMenuname(layerManagerHelp),parent(),SLOT(openLayerManager()));
// reset layer
// restore layer
// store layer as
// menu.addSeparator();
menu.addAction(helpWindow::getIcon(layerManagerHelp),helpWindow::getMenuname(layerManagerHelp),parent(),SLOT(openLayerManager()));
// layer setup ???
menu.exec(QCursor::pos());
#endif
}

void layerTool::layersAsList(){
  setup::layerDockStyle=2;
  placeButtons();update();
}
void layerTool::layersAsBlock(){
  setup::layerDockStyle=1;
  placeButtons();update();
}
void layerTool::layerSortName(){
  sorting=1;
  placeButtons();update();
}
void layerTool::layerSortNumber(){
  sorting=0;
  placeButtons();update();
}
