/* kartei.cc
 * This file belongs to Worker, a file manager for UN*X/X11.
 * Copyright (C) 2004-2019 Ralf Hoffmann.
 * You can contact me at: ralf@boomerangsworld.de
 *   or http://www.boomerangsworld.de/worker
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "kartei.h"
#include "acontainer.h"
#include "karteibutton.h"
#include <algorithm>

Kartei::Kartei( AGUIX *parent,
		int x,
		int y,
		int width,
		int height,
		std::string title  ) : AWindow( parent, x, y, width, height, title )
{
  cont = new AContainer( this, 1, 2 );
  cont->setMinSpace( 0 );
  cont->setMaxSpace( 0 );
  cont->setBorderWidth( 1 );
  setContainer( cont, true );
  optionkb = NULL;
  curOption = 0;
}

Kartei::~Kartei()
{
  destroy();
}

void Kartei::doCreateStuff()
{
  AWindow::doCreateStuff();
  if ( _created == false ) return;

  optionkb = new KarteiButton( _aguix, 0, 0, 100, 0 );
  cont->add( optionkb, 0, 0, AContainer::CO_INCW );
  optionkb->setOptionChangeCallback( optionChangeCallback, this );

  cont->setBorderWidth( 1 );
  return;
}

void Kartei::setOption( AWindow *twin, unsigned int option, const char *optionname )
{
  if ( twin == NULL ) return;
  if ( optionname == NULL ) return;
  
  if ( option > options.size() ) option = options.size();
  if ( option == options.size() ) options.resize( option + 1 );
  options[option] = twin;

  while ( optionkb->setOption( option, optionname ) < 0 ) optionkb->addOption( "" );
  optionkb->resize( optionkb->getMaxSize(), optionkb->getHeight() );
  cont->readLimits();
  if ( curOption == option ) showCurOption();
  redraw();
}

void Kartei::updateOption( unsigned int option, const char *optionname )
{
    if ( optionname == NULL ) return;
  
    if ( option >= options.size() ) return;

    optionkb->setOption( option, optionname );
    optionkb->resize( optionkb->getMaxSize(), optionkb->getHeight() );
    cont->readLimits();
    if ( curOption == option ) showCurOption();
    redraw();
}

void Kartei::updateOption( unsigned int option, const std::string &optionname )
{
    updateOption( option,
                  optionname.c_str() );
}

void Kartei::showCurOption()
{
  AWindow *twin, *otwin;
  unsigned int i;
  bool find_new_focus = false;

  if ( curOption >= options.size() ) return;
  twin = options[curOption];
  if ( std::find( getChilds().begin(), getChilds().end(), twin ) == getChilds().end() ) return;
  
  for ( i = 0; i < options.size(); i++ ) {
    if ( i == curOption ) continue;
    otwin = options[i];
    if ( std::find( getChilds().begin(), getChilds().end(), twin ) == getChilds().end() ) continue;
    if ( otwin->contains( getFocusOwner() ) == true )
      find_new_focus = true;
    otwin->hide();
  }
  twin->show();
  cont->add( twin, 0, 1 );
  cont->rearrange();

  if ( find_new_focus == true ) {
    // find new focus element as the old one is now hidden
    Widget *w = twin->searchNextFocus( NULL );
    if ( w != NULL )
      applyFocus( w );
  }
}

void Kartei::maximize()
{
  AWindow *twin;
  unsigned int i;
  int tw = 0, th = 0;

  for ( i = 0; i < options.size(); i++ ) {
    twin = options[i];
    if ( std::find( getChilds().begin(), getChilds().end(), twin ) == getChilds().end() ) continue;
    twin->contMaximize();
    if ( twin->getWidth() > tw ) tw = twin->getWidth();
    if ( twin->getHeight() > th ) th = twin->getHeight();
  }
  cont->setMinWidth( tw, 0, 1 );
  cont->setMinHeight( th, 0, 1 );
}

void Kartei::optionChangeCallback( Kartei *k1, unsigned int option )
{
  if ( k1 == NULL ) return;
  k1->optionChange( option );
}

void Kartei::optionChange( unsigned int option )
{
  unsigned int old_option = curOption;

  if ( curOption != option ) {
    curOption = option;
    if ( curOption >= options.size() ) curOption = 0;
    if ( old_option != curOption )
      optionkb->setOption( curOption);
    showCurOption();
    boxRedraw();
  }
}

void Kartei::boxRedraw()
{
  int ty;
  
  if ( optionkb != NULL ) ty = optionkb->getY() + optionkb->getHeight();
  else ty = 0;

  _aguix->setFG( 0, 2 );
  _aguix->DrawLine( win, 0, 0, ty, 0, _h - 1 );
  _aguix->setFG( 0, 1 );
  _aguix->DrawLine( win, 0, 0, _h - 1, _w - 1, _h - 1 );
  _aguix->DrawLine( win, 0, _w - 1, _h - 1, _w - 1, ty - 1 );
}

bool Kartei::handleMessage(XEvent *E,Message *msg)
{
  if ( ( msg->type == Expose ) &&
       ( msg->window == win ) ) {
    boxRedraw();
  }

  return AWindow::handleMessage( E, msg );
}

void Kartei::doDestroyStuff()
{
  AWindow::doDestroyStuff();
  optionkb = NULL;
  curOption = 0;
}

int Kartei::getCurOption() const
{
  return curOption;
}
