/**********************************************************************
** Copyright (C) 2005-2008 Trolltech ASA.  All rights reserved.
**
** This file is part of TQt Designer.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free TQt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** Licensees holding valid TQt Commercial licenses may use this file in
** accordance with the TQt Commercial License Agreement provided with
** the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/

#ifndef WIDGETFACTORY_H
#define WIDGETFACTORY_H

#include <tqvariant.h>
#include <tqiconset.h>
#include <tqstring.h>
#include <tqintdict.h>
#include <tqtabwidget.h>
#include <tqpixmap.h>
#include <tqsize.h>
#include <tqpainter.h>
#include <tqevent.h>
#include <tqobjectlist.h>
#include <tqlabel.h>
#include <tqwizard.h>
#include <tqptrdict.h>
#include <tqpushbutton.h>
#include <tqtoolbutton.h>
#include <tqcheckbox.h>
#include <tqradiobutton.h>
#include <tqbuttongroup.h>
#include <tqwidgetstack.h>
#include <tqguardedptr.h>
#include <tqtoolbox.h>

#include "metadatabase.h"
#include "tqwidgetfactory.h"

class TQWidget;
class TQLayout;
class FormWindow;

class CustomWidgetFactory : public TQWidgetFactory
{
public:
    CustomWidgetFactory();
    TQWidget *createWidget( const TQString &className, TQWidget *parent, const char *name ) const;

};

class WidgetFactory : public TQt
{
    friend class CustomWidgetFactory;

public:
    enum LayoutType {
	HBox,
	VBox,
	Grid,
	NoLayout
    };

    static TQWidget *create( int id, TQWidget *parent, const char *name = 0, bool init = TRUE,
			    const TQRect *rect = 0, Qt::Orientation orient = Qt::Horizontal );
    static TQLayout *createLayout( TQWidget *widget, TQLayout* tqlayout, LayoutType type );
    static void deleteLayout( TQWidget *widget );

    static LayoutType layoutType( TQWidget *w );
    static LayoutType layoutType( TQWidget *w, TQLayout *&tqlayout );
    static LayoutType layoutType( TQLayout *tqlayout );
    static TQWidget *layoutParent( TQLayout *tqlayout );

    static TQWidget* containerOfWidget( TQWidget *w );
    static TQWidget* widgetOfContainer( TQWidget *w );

    static bool isPassiveInteractor( TQT_BASE_OBJECT_NAME* o );
    static const char* classNameOf( TQT_BASE_OBJECT_NAME* o );

    static void initChangedProperties( TQT_BASE_OBJECT_NAME *o );

    static bool hasSpecialEditor( int id, TQObject *editorWidget );
    static bool hasItems( int id, TQObject *editorWidget );
    static void editWidget( int id, TQWidget *parent, TQWidget *editWidget, FormWindow *fw );

    static bool canResetProperty( TQT_BASE_OBJECT_NAME *w, const TQString &propName );
    static bool resetProperty( TQT_BASE_OBJECT_NAME *w, const TQString &propName );
    static TQVariant defaultValue( TQT_BASE_OBJECT_NAME *w, const TQString &propName );
    static TQString defaultCurrentItem( TQT_BASE_OBJECT_NAME *w, const TQString &propName );

    static TQVariant property( TQT_BASE_OBJECT_NAME *w, const char *name );
    static void saveDefaultProperties( TQT_BASE_OBJECT_NAME *w, int id );
    static void saveChangedProperties( TQT_BASE_OBJECT_NAME *w, int id );

    static TQString defaultSignal( TQT_BASE_OBJECT_NAME *w );

private:
    static TQWidget *createWidget( const TQString &className, TQWidget *parent, const char *name, bool init,
				  const TQRect *r = 0, Qt::Orientation orient = Qt::Horizontal );
    static TQWidget *createCustomWidget( TQWidget *parent, const char *name, MetaDataBase::CustomWidget *w );

    static TQGuardedPtr<TQObject> *lastPassiveInteractor;
    static bool lastWasAPassiveInteractor;
};


class TQDesignerTabWidget : public TQTabWidget
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int currentPage READ currentPage WRITE setCurrentPage STORED false DESIGNABLE true )
    Q_PROPERTY( TQString pageTitle READ pageTitle WRITE setPageTitle STORED false DESIGNABLE true )
    Q_PROPERTY( TQCString pageName READ pageName WRITE setPageName STORED false DESIGNABLE true )
public:
    TQDesignerTabWidget( TQWidget *parent, const char *name );

    int currentPage() const;
    void setCurrentPage( int i );
    TQString pageTitle() const;
    void setPageTitle( const TQString& title );
    TQCString pageName() const;
    void setPageName( const TQCString& name );

    int count() const;
    TQTabBar *tabBar() const { return TQTabWidget::tabBar(); }

    bool eventFilter( TQObject*, TQEvent* );

private:
    TQPoint pressPoint;
    TQWidget *dropIndicator;
    TQWidget *dragPage;
    TQString dragLabel;
     bool mousePressed;
};

class TQDesignerWidgetStack : public TQWidgetStack
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int currentPage READ currentPage WRITE setCurrentPage STORED false DESIGNABLE true )
    Q_PROPERTY( TQCString pageName READ pageName WRITE setPageName STORED false DESIGNABLE true )
public:
    TQDesignerWidgetStack( TQWidget *parent, const char *name );

    int currentPage() const;
    void setCurrentPage( int i );
    TQCString pageName() const;
    void setPageName( const TQCString& name );

    int count() const;
    TQWidget* page( int i ) const;

    int insertPage( TQWidget *p, int i = -1 );
    int removePage( TQWidget *p );

public Q_SLOTS:
    void updateButtons();

protected:
    void resizeEvent( TQResizeEvent *e ) {
	TQWidgetStack::resizeEvent( e );
	updateButtons();
    }

    void showEvent( TQShowEvent *e ) {
	TQWidgetStack::showEvent( e );
	updateButtons();
    }

private Q_SLOTS:
    void prevPage();
    void nextPage();

private:
    TQPtrList<TQWidget> pages;
    TQToolButton *prev, *next;

};

class TQDesignerWizard : public TQWizard
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int currentPage READ currentPageNum WRITE setCurrentPage STORED false DESIGNABLE true )
    Q_PROPERTY( TQString pageTitle READ pageTitle WRITE setPageTitle STORED false DESIGNABLE true )
    Q_PROPERTY( TQCString pageName READ pageName WRITE setPageName STORED false DESIGNABLE true )
    TQ_OVERRIDE( bool modal READ isModal WRITE setModal )

public:
    TQDesignerWizard( TQWidget *parent, const char *name ) 
        : TQWizard( parent, name ), modal(FALSE) {}

    int currentPageNum() const;
    void setCurrentPage( int i );
    TQString pageTitle() const;
    void setPageTitle( const TQString& title );
    TQCString pageName() const;
    void setPageName( const TQCString& name );
    int pageNum( TQWidget *page );
    void addPage( TQWidget *p, const TQString & );
    void removePage( TQWidget *p );
    void insertPage( TQWidget *p, const TQString &t, int index );
    bool isPageRemoved( TQWidget *p ) { return (removedPages.find( p ) != 0); }

    bool isModal() const { return modal; }
    void setModal(bool b) { modal = b; }

    void reject() {}

private:
    struct Page
    {
	Page( TQWidget *a, const TQString &b ) : p( a ), t( b ) {}
	Page() : p( 0 ), t( TQString() ) {}
	TQWidget *p;
	TQString t;
    };
    TQPtrDict<TQWidget> removedPages;
    bool modal;

};

class TQLayoutWidget : public TQWidget
{
    Q_OBJECT
    TQ_OBJECT

public:
    TQLayoutWidget( TQWidget *parent, const char *name ) : TQWidget( parent, name ), sp( TQWidget::tqsizePolicy() ) {}

    TQSizePolicy sizePolicy() const;
    void updateSizePolicy();

protected:
    void paintEvent( TQPaintEvent * );
    bool event( TQEvent * );
    TQSizePolicy sp;

};


class CustomWidget : public TQWidget
{
    Q_OBJECT
    TQ_OBJECT

public:
    CustomWidget( TQWidget *parent, const char *name, MetaDataBase::CustomWidget *cw )
	: TQWidget( parent, name ), cusw( cw ) {
	    alwaysExpand = parentWidget() && parentWidget()->inherits( "FormWindow" );
	    tqsetSizePolicy( cw->sizePolicy );
	    if ( !alwaysExpand )
		setBackgroundMode( TQt::PaletteDark );
    }

    TQSize tqsizeHint() const {
	TQSize sh = cusw->tqsizeHint;
	if ( sh.isValid() )
	    return sh;
	return TQWidget::tqsizeHint();
    }

    TQString realClassName() { return cusw->className; }
    MetaDataBase::CustomWidget *customWidget() const { return cusw; }

protected:
    void paintEvent( TQPaintEvent *e );

    MetaDataBase::CustomWidget *cusw;
    bool alwaysExpand;

};


class Line : public TQFrame
{
    Q_OBJECT
    TQ_OBJECT

    Q_PROPERTY( Qt::Orientation orientation READ orientation WRITE setOrientation )
    TQ_OVERRIDE( int frameWidth DESIGNABLE false )
    TQ_OVERRIDE( Shape frameShape DESIGNABLE false )
    TQ_OVERRIDE( TQRect frameRect DESIGNABLE false )
    TQ_OVERRIDE( TQRect contentsRect DESIGNABLE false )
public:
    Line( TQWidget *parent, const char *name )
	: TQFrame( parent, name, TQt::WMouseNoMask ) {
	    setFrameStyle( HLine | Sunken );
    }

    void setOrientation( Qt::Orientation orient ) {
	if ( orient == Qt::Horizontal )
	    setFrameShape( HLine );
	else
	    setFrameShape( VLine );
    }
    Qt::Orientation orientation() const {
	return frameShape() == HLine ? Qt::Horizontal : Qt::Vertical;
    }
};

class TQDesignerLabel : public TQLabel
{
    Q_OBJECT
    TQ_OBJECT

    Q_PROPERTY( TQCString buddy READ buddyWidget WRITE setBuddyWidget )

public:
    TQDesignerLabel( TQWidget *parent = 0, const char *name = 0 )
	: TQLabel( parent, name ) { myBuddy = 0; }

    void setBuddyWidget( const TQCString &b ) {
	myBuddy = b;
	updateBuddy();
    }
    TQCString buddyWidget() const {
	return myBuddy;
    };

protected:
    void showEvent( TQShowEvent *e ) {
	TQLabel::showEvent( e );
	updateBuddy();
    }


private:
    void updateBuddy();

    TQCString myBuddy;

};

class TQDesignerWidget : public TQWidget
{
    Q_OBJECT
    TQ_OBJECT

public:
    TQDesignerWidget( FormWindow *fw, TQWidget *parent, const char *name )
	: TQWidget( parent, name, TQt::WResizeNoErase ), formwindow( fw ) {
	    need_frame = parent && parent->inherits("TQDesignerWidgetStack" );
    }

protected:
    void resizeEvent( TQResizeEvent* e);
    void paintEvent( TQPaintEvent *e );

private:
    FormWindow *formwindow;
    uint need_frame : 1;

};

class TQDesignerDialog : public TQDialog
{
    Q_OBJECT
    TQ_OBJECT
    TQ_OVERRIDE( bool modal READ isModal WRITE setModal )

public:
    TQDesignerDialog( FormWindow *fw, TQWidget *parent, const char *name )
	: TQDialog( parent, name, FALSE, (WFlags)TQt::WResizeNoErase ), formwindow( fw ), modal(FALSE) {}

    bool isModal() const { return modal; }
    void setModal(bool b) { modal = b; }

protected:
    void paintEvent( TQPaintEvent *e );

private:
    FormWindow *formwindow;
    bool modal;

};

class TQDesignerToolButton : public TQToolButton
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int buttonGroupId READ buttonGroupId WRITE setButtonGroupId )

public:
    TQDesignerToolButton( TQWidget *parent, const char *name )
	: TQToolButton( parent, name ) {}

    bool isInButtonGroup() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" );
    }
    int buttonGroupId() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ? ( (TQButtonGroup*)parentWidget() )->id( (TQButton*)this ) : -1;
    }
    void setButtonGroupId( int id ) {
	if ( parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ) {
	    ( (TQButtonGroup*)parentWidget() )->remove( this );
	    ( (TQButtonGroup*)parentWidget() )->insert( this, id );
	}
    }
};

class TQDesignerRadioButton : public TQRadioButton
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int buttonGroupId READ buttonGroupId WRITE setButtonGroupId )

public:
    TQDesignerRadioButton( TQWidget *parent, const char *name )
	: TQRadioButton( parent, name ) {}

    bool isInButtonGroup() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" );
    }
    int buttonGroupId() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ? ( (TQButtonGroup*)parentWidget() )->id( (TQButton*)this ) : -1;
    }
    void setButtonGroupId( int id ) {
	if ( parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ) {
	    ( (TQButtonGroup*)parentWidget() )->remove( this );
	    ( (TQButtonGroup*)parentWidget() )->insert( this, id );
	}
    }

    void setFocusPolicy( Qt::FocusPolicy policy );
};

class TQDesignerPushButton : public TQPushButton
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int buttonGroupId READ buttonGroupId WRITE setButtonGroupId )

public:
    TQDesignerPushButton( TQWidget *parent, const char *name )
	: TQPushButton( parent, name ) {}

    bool isInButtonGroup() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" );
    }
    int buttonGroupId() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ? ( (TQButtonGroup*)parentWidget() )->id( (TQButton*)this ) : -1;
    }
    void setButtonGroupId( int id ) {
	if ( parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ) {
	    ( (TQButtonGroup*)parentWidget() )->remove( this );
	    ( (TQButtonGroup*)parentWidget() )->insert( this, id );
	}
    }

};

class TQDesignerCheckBox : public TQCheckBox
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( int buttonGroupId READ buttonGroupId WRITE setButtonGroupId )

public:
    TQDesignerCheckBox( TQWidget *parent, const char *name )
	: TQCheckBox( parent, name ) {}

    bool isInButtonGroup() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" );
    }
    int buttonGroupId() const {
	return parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ? ( (TQButtonGroup*)parentWidget() )->id( (TQButton*)this ) : -1;
    }
    void setButtonGroupId( int id ) {
	if ( parentWidget() && parentWidget()->inherits( "TQButtonGroup" ) ) {
	    ( (TQButtonGroup*)parentWidget() )->remove( this );
	    ( (TQButtonGroup*)parentWidget() )->insert( this, id );
	}
    }

};

class TQDesignerToolBox : public TQToolBox
{
    Q_OBJECT
    TQ_OBJECT
    Q_PROPERTY( TQString itemLabel READ itemLabel WRITE setItemLabel STORED false DESIGNABLE true )
    Q_PROPERTY( TQCString itemName READ itemName WRITE setItemName STORED false DESIGNABLE true )
    Q_PROPERTY( BackgroundMode itemBackgroundMode READ itemBackgroundMode WRITE setItemBackgroundMode STORED false DESIGNABLE true )

public:
    TQDesignerToolBox( TQWidget *parent, const char *name );

    TQString itemLabel() const;
    void setItemLabel( const TQString &l );
    TQCString itemName() const;
    void setItemName( const TQCString &n );
    TQt::BackgroundMode itemBackgroundMode() const;
    void setItemBackgroundMode( TQt::BackgroundMode );

protected:
    void itemInserted( int index );
};

#endif
