/*
 * Kivio - Visual Modelling and Flowcharting
 * Copyright (C) 2000 theKompany.com
 *
 * 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 Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
#include <ttdetoolbarbutton.h>

#include <tqtimer.h>
#include <tqtooltip.h>
#include <tqpopupmenu.h>
#include <tqcursor.h>
#include <tqpainter.h>
#include <tqdrawutil.h>
#include <tqstyle.h>

#include <tdeversion.h>
#include <tdeapplication.h>
#include <kiconeffect.h>
#include <kiconloader.h>
#include <tdeglobalsettings.h>

// Delay in ms before delayed popup pops up
#define POPUP_DELAY 500

class TTDEToolBarButton::TTDEToolBarButtonPrivate
{
public:
  TTDEToolBarButtonPrivate()
  {
    m_iconMode     = TK::IconOnly;
    m_isPopup      = false;
    m_isToggle     = false;
    m_isOn         = false;
    m_isRaised     = false;
    m_autoRaised   = true;
    ignoreNextMousePress = false;

    m_text         = TQString();
    m_iconName     = TQString();
    m_arrowPressed = false;
    m_delayTimer   = 0L;
    m_popup        = 0L;

    m_disabledIconName = TQString();
    m_defaultIconName  = TQString();

    m_instance = TDEGlobal::instance();
  }

  ~TTDEToolBarButtonPrivate()
  {
    delete m_delayTimer;
    m_delayTimer = 0;
  }

  bool    m_isPopup;
  bool    m_isToggle;
  bool    m_isOn;
  bool    m_isRaised;
  bool    m_autoRaised;
  bool    m_arrowPressed;
  bool    ignoreNextMousePress;

  TQString m_text;
  TQString m_iconName;
  TQString m_disabledIconName;
  TQString m_defaultIconName;

  TK::IconMode m_iconMode;

  TQTimer     *m_delayTimer;
  TQPopupMenu *m_popup;

  TDEInstance  *m_instance;
};

TTDEToolBarButton::TTDEToolBarButton( const TQString& icon, const TQString& txt,
                                        TQWidget* parent, const char* name,
                                        TDEInstance *instance )
: TQToolButton(parent,name)
{
  d = new TTDEToolBarButtonPrivate;
  d->m_text = txt;
  d->m_instance = instance;

  setFocusPolicy( TQWidget::NoFocus );

  connect(this, TQ_SIGNAL(clicked()), TQ_SLOT(slotClicked()) );
  connect(this, TQ_SIGNAL(pressed()), TQ_SLOT(slotPressed()) );
  connect(this, TQ_SIGNAL(released()), TQ_SLOT(slotReleased()) );

  installEventFilter(this);

  setIcon(icon);
  modeChange();
}

TTDEToolBarButton::TTDEToolBarButton( const TQPixmap& pixmap, const TQString& txt, TQWidget* parent, const char* name )
: TQToolButton(parent,name )
{
  d = new TTDEToolBarButtonPrivate;
  d->m_text = txt;

  setFocusPolicy( TQWidget::NoFocus );

  connect(this, TQ_SIGNAL(clicked()), TQ_SLOT(slotClicked()) );
  connect(this, TQ_SIGNAL(pressed()), TQ_SLOT(slotPressed()) );
  connect(this, TQ_SIGNAL(released()), TQ_SLOT(slotReleased()) );

  installEventFilter(this);

  setPixmap(pixmap);
  modeChange();
}

TTDEToolBarButton::~TTDEToolBarButton()
{
  delete d;
}

TQString TTDEToolBarButton::text()
{
  return d->m_text;
}

void TTDEToolBarButton::modeChange()
{
  TQToolTip::add(this,d->m_text);

  int border = 3;
  int w = 2*border;
  int h = 2*border;

  if (pixmap()) {
    w += pixmap()->width();
    h = TQMAX(h,pixmap()->height()+2*border);
    if (d->m_iconMode == TK::IconAndText && !d->m_text.isEmpty())
      w += border;
  }

  if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty())
  {
    TQFont tmp_font = TDEGlobalSettings::toolBarFont();
    TQFontMetrics fm(tmp_font);

    h = TQMAX(h,fm.lineSpacing()+2*border);
    w += fm.width(d->m_text);
  }

  if (d->m_popup && !d->m_isToggle)
    w += 11;

  TQSize size(w,h);
  setMinimumSize(size);

  updateGeometry();
}

void TTDEToolBarButton::setEnabled( bool enabled )
{
  if (isEnabled()==enabled)
    return;

  TQToolButton::setPixmap( (enabled ? defaultPixmap : disabledPixmap) );
  TQToolButton::setEnabled( enabled );
}

void TTDEToolBarButton::setText( const TQString& text)
{
  d->m_text = text;
  repaint(false);
}

void TTDEToolBarButton::setIcon( const TQString& icon )
{
  d->m_iconName = icon;
  int iconSize = 16;

  setPixmap( BarIcon(icon, iconSize, TDEIcon::ActiveState, d->m_instance), false );
  setDisabledPixmap( BarIcon(icon, iconSize, TDEIcon::DisabledState, d->m_instance) );
  setDefaultPixmap( BarIcon(icon, iconSize, TDEIcon::DefaultState, d->m_instance) );
}

void TTDEToolBarButton::setDisabledIcon( const TQString &icon )
{
  d->m_disabledIconName = icon;
  int iconSize = 16;
  setDisabledPixmap( BarIcon(icon, iconSize, TDEIcon::DisabledState, d->m_instance) );
}

void TTDEToolBarButton::setDefaultIcon( const TQString &icon )
{
  d->m_defaultIconName = icon;
  int iconSize = 16;
  setDefaultPixmap( BarIcon(icon, iconSize, TDEIcon::DefaultState, d->m_instance) );
}

TQPixmap TTDEToolBarButton::getActivePixmap() const
{
  return activePixmap;
}

void TTDEToolBarButton::setPixmap( const TQPixmap &pixmap )
{
  setPixmap( pixmap, true );
}

void TTDEToolBarButton::setPixmap( const TQPixmap &pixmap, bool generate )
{
  activePixmap = pixmap;

  if ( generate )
  {
    makeDefaultPixmap();
    makeDisabledPixmap();
  }
  else
  {
    if (defaultPixmap.isNull())
      defaultPixmap = activePixmap;
    if (disabledPixmap.isNull())
      disabledPixmap = activePixmap;
  }

  TQToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}

void TTDEToolBarButton::setDefaultPixmap( const TQPixmap &pixmap )
{
  defaultPixmap = pixmap;
  TQToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}

void TTDEToolBarButton::setDisabledPixmap( const TQPixmap &pixmap )
{
  disabledPixmap = pixmap;
  TQToolButton::setPixmap( isEnabled() ? defaultPixmap : disabledPixmap );
}

void TTDEToolBarButton::setPopup(TQPopupMenu *p)
{
  d->m_popup = p;
  d->m_popup->setFont(TDEGlobalSettings::toolBarFont());
  p->installEventFilter(this);

  modeChange();
}

TQPopupMenu *TTDEToolBarButton::popup()
{
  return d->m_popup;
}

void TTDEToolBarButton::setDelayedPopup (TQPopupMenu *p, bool toggle )
{
  d->m_isPopup = true;
  setToggle(toggle);

  if (!d->m_delayTimer) {
    d->m_delayTimer = new TQTimer(this);
    connect(d->m_delayTimer, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotDelayTimeout()));
  }

  setPopup(p);
}

void TTDEToolBarButton::setRaised(bool f)
{
  d->m_isRaised = f;
  repaint(false);
}

void TTDEToolBarButton::setAutoRaised(bool f)
{
  d->m_autoRaised = f;
}

void TTDEToolBarButton::leaveEvent(TQEvent *)
{
  if (!d->m_isToggle && !(d->m_popup && d->m_popup->isVisible()) ) {
    TQToolButton::setPixmap(isEnabled() ? defaultPixmap : disabledPixmap);
    if (d->m_autoRaised)
      setRaised(false);
  }
}

void TTDEToolBarButton::enterEvent(TQEvent *)
{
  if (!d->m_isToggle) {
    if (isEnabled()) {
      TQToolButton::setPixmap(activePixmap);
      if (d->m_autoRaised)
        setRaised(true);
    } else {
      TQToolButton::setPixmap(disabledPixmap);
    }
    repaint(false);
  }
}

bool TTDEToolBarButton::eventFilter(TQObject *o, TQEvent *ev)
{
  if ( o == this )
    if (ev->type() == TQEvent::MouseButtonPress && d->m_popup && d->m_isPopup ) {
      if (!d->m_isToggle) {
        d->m_arrowPressed = arrowPressed( mapFromGlobal(TQCursor::pos()) );
      } else {
        d->m_delayTimer->start(POPUP_DELAY);
      }
    }

  if ( o == d->m_popup) {
    switch (ev->type())
    {
      case TQEvent::Show:
        on(true);
        return false;
      case TQEvent::Hide:
        on(false);
        setDown(false);
        if ( !geometry().contains(parentWidget()->mapFromGlobal(TQCursor::pos())) )
          leaveEvent(0L);
        return false;
        break;
      case TQEvent::MouseButtonPress: {
        d->m_arrowPressed = arrowPressed( mapFromGlobal(TQCursor::pos()) );
        d->ignoreNextMousePress = d->m_arrowPressed;
        break;
      }
      default:
        break;
    }
  }
  return false;
}

void TTDEToolBarButton::drawButton( TQPainter* p )
{
#define DRAW_PIXMAP_AND_TEXT \
  int x = 3;\
  if (pixmap()) {\
    style().drawItem( p, TQRect( x, 0, pixmap()->width(), height() ), AlignCenter, colorGroup(), isEnabled(), pixmap(), TQString() );\
    if (d->m_iconMode==TK::IconAndText && !d->m_text.isEmpty()) {\
      x += pixmap()->width() + 3;\
    }\
  }\
  if ((d->m_iconMode==TK::IconAndText||d->m_iconMode==TK::TextOnly) && !d->m_text.isEmpty()) {\
    TQFontMetrics fm(TDEGlobalSettings::toolBarFont());\
    style().drawItem( p, TQRect( x, 0, fm.width(d->m_text), height() ), AlignCenter, colorGroup(), isEnabled(), 0, d->m_text );\
  }

  const char* arrow[] = {
  "7 4 2 1",
  "# c Black",
  ". c None",
  "#######",
  ".#####.",
  "..###..",
  "...#..."};
  TQPixmap arrow_pix(arrow);
  bool f = d->m_isOn || isDown();

    if (d->m_popup && !d->m_isToggle)
    {
        if (d->m_isPopup)
        {
            TQStyle::SFlags flags   = TQStyle::Style_Default;
            if (isEnabled()) 	flags |= TQStyle::Style_Enabled;
            if (isOn()) 		flags |= TQStyle::Style_On;
            if (d->m_isRaised)	flags |= TQStyle::Style_Raised;
            if (hasFocus())	flags |= TQStyle::Style_HasFocus;

            style().drawComplexControl( TQStyle::CC_ToolButton, p, this, TQRect( 0, 0, width()-12, height() ), colorGroup(), flags, TQStyle::SC_ToolButton );
            style().drawComplexControl( TQStyle::CC_ToolButton, p, this, TQRect( width()-13, 0, 13, height() ), colorGroup(), flags, TQStyle::SC_ToolButton );
            style().drawItem( p, TQRect( width()-13, 0, 13, height() ), AlignCenter, colorGroup(), isEnabled(), &arrow_pix, TQString() );
            if ( d->m_isRaised )
                qDrawShadeLine( p, width()-12, 0, width()-12, height(), colorGroup(), true );
            DRAW_PIXMAP_AND_TEXT
        } else {
            style().drawControl( TQStyle::CE_PushButton, p, this, TQRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
            DRAW_PIXMAP_AND_TEXT
            int z = f ? 1:0;
            p->drawPixmap(width()-11+z,(height()-4)/2+z ,arrow_pix);
        }
    } else {
        style().drawControl( TQStyle::CE_PushButton, p, this, TQRect( 0, 0, width(), height() ), isEnabled() ? colorGroup() : palette().disabled(), f );
        DRAW_PIXMAP_AND_TEXT
    }
}

void TTDEToolBarButton::paletteChange(const TQPalette &)
{
  makeDisabledPixmap();
  if ( !isEnabled() )
    TQToolButton::setPixmap( disabledPixmap );
  else
    TQToolButton::setPixmap( defaultPixmap );
  repaint(false);
}

void TTDEToolBarButton::makeDefaultPixmap()
{
  if (activePixmap.isNull())
    return;

  TDEIconEffect effect;
  defaultPixmap = effect.apply(activePixmap, TDEIcon::Toolbar, TDEIcon::DefaultState);
}

void TTDEToolBarButton::makeDisabledPixmap()
{
  if (activePixmap.isNull())
    return;

  TDEIconEffect effect;
  disabledPixmap = effect.apply(activePixmap, TDEIcon::Toolbar, TDEIcon::DisabledState);
}

TQSize TTDEToolBarButton::sizeHint() const
{
    return minimumSize();
}

TQSize TTDEToolBarButton::minimumSizeHint() const
{
    return minimumSize();
}

void TTDEToolBarButton::showMenu()
{
  TQPoint p ( mapToGlobal( TQPoint( 0, 0 ) ) );
  const int deskHeight = TDEGlobalSettings::desktopGeometry(this).height();
  if ( p.y() + height() + d->m_popup->height() > deskHeight )
      p.setY( p.y() - d->m_popup->height() );
  else
      p.setY( p.y() + height( ));

  d->m_popup->popup(p);
}

void TTDEToolBarButton::slotDelayTimeout()
{
  d->m_delayTimer->stop();
  showMenu();
}

void TTDEToolBarButton::slotClicked()
{
  if ( d->ignoreNextMousePress ) {
    d->ignoreNextMousePress=false;
    return;
  }

  if (d->m_popup && !d->m_isPopup)
    showMenu();
  else
    emit buttonClicked();
}

void TTDEToolBarButton::slotPressed()
{
  if ( d->ignoreNextMousePress )
    return;

  if (d->m_popup) {
    if (!d->m_isPopup || d->m_isPopup && d->m_arrowPressed)
      showMenu();
  }
  else
    emit buttonPressed();

  d->ignoreNextMousePress = false;
}

void TTDEToolBarButton::slotReleased()
{
  if (d->m_popup && d->m_isPopup)
    d->m_delayTimer->stop();

  emit buttonReleased();
}

void TTDEToolBarButton::slotToggled()
{
  emit buttonToggled();
}

void TTDEToolBarButton::on(bool flag)
{
  d->m_isOn = flag;
  repaint();
}

void TTDEToolBarButton::toggle()
{
  on(!d->m_isOn);
}

void TTDEToolBarButton::setToggle(bool flag)
{
  d->m_isToggle = flag;
  if (flag == true)
    connect(this, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotToggled()));
  else
    disconnect(this, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(slotToggled()));

  modeChange();
  repaint();
}

void TTDEToolBarButton::setIconMode( TK::IconMode m )
{
  d->m_iconMode = m;
  modeChange();
  repaint();
}

#include <ttdetoolbarbutton.moc>
