summaryrefslogtreecommitdiffstats
path: root/kig/modes
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce599e4f9f94b4eb00c1b5edb85bce5431ab3df2 (patch)
treed3bb9f5d25a2dc09ca81adecf39621d871534297 /kig/modes
downloadtdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.tar.gz
tdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeedu@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kig/modes')
-rw-r--r--kig/modes/Makefile.am39
-rw-r--r--kig/modes/base_mode.cc160
-rw-r--r--kig/modes/base_mode.h64
-rw-r--r--kig/modes/construct_mode.cc572
-rw-r--r--kig/modes/construct_mode.h154
-rw-r--r--kig/modes/dragrectmode.cc180
-rw-r--r--kig/modes/dragrectmode.h104
-rw-r--r--kig/modes/edittype.cc107
-rw-r--r--kig/modes/edittype.h48
-rw-r--r--kig/modes/edittypebase.ui287
-rw-r--r--kig/modes/label.cc589
-rw-r--r--kig/modes/label.h129
-rw-r--r--kig/modes/linkslabel.cpp134
-rw-r--r--kig/modes/linkslabel.h85
-rw-r--r--kig/modes/macro.cc245
-rw-r--r--kig/modes/macro.h68
-rw-r--r--kig/modes/macrowizard.cc90
-rw-r--r--kig/modes/macrowizard.h43
-rw-r--r--kig/modes/macrowizardbase.ui188
-rw-r--r--kig/modes/mode.cc133
-rw-r--r--kig/modes/mode.h91
-rw-r--r--kig/modes/moving.cc245
-rw-r--r--kig/modes/moving.h101
-rw-r--r--kig/modes/normal.cc306
-rw-r--r--kig/modes/normal.h74
-rw-r--r--kig/modes/popup.cc1200
-rw-r--r--kig/modes/popup.h153
-rw-r--r--kig/modes/textlabelwizard.cc95
-rw-r--r--kig/modes/textlabelwizard.h46
-rw-r--r--kig/modes/textlabelwizardbase.ui113
-rw-r--r--kig/modes/typesdialog.cpp282
-rw-r--r--kig/modes/typesdialog.h70
-rw-r--r--kig/modes/typesdialogbase.ui337
33 files changed, 6532 insertions, 0 deletions
diff --git a/kig/modes/Makefile.am b/kig/modes/Makefile.am
new file mode 100644
index 00000000..5f7518e5
--- /dev/null
+++ b/kig/modes/Makefile.am
@@ -0,0 +1,39 @@
+INCLUDES=$(all_includes)
+
+noinst_LTLIBRARIES=libmodes.la
+libmodes_la_SOURCES= \
+ base_mode.cc \
+ construct_mode.cc \
+ dragrectmode.cc \
+ edittype.cc \
+ edittypebase.ui \
+ label.cc \
+ linkslabel.cpp \
+ macro.cc \
+ macrowizard.cc \
+ macrowizardbase.ui \
+ mode.cc \
+ moving.cc \
+ normal.cc \
+ popup.cc \
+ textlabelwizard.cc \
+ textlabelwizardbase.ui \
+ typesdialog.cpp \
+ typesdialogbase.ui
+noinst_HEADERS=\
+ base_mode.h \
+ construct_mode.h \
+ dragrectmode.h \
+ edittype.h \
+ label.h \
+ linkslabel.h \
+ macro.h \
+ macrowizard.h \
+ mode.h \
+ moving.h \
+ normal.h \
+ popup.h \
+ textlabelwizard.h \
+ typesdialog.h
+
+METASOURCES=AUTO
diff --git a/kig/modes/base_mode.cc b/kig/modes/base_mode.cc
new file mode 100644
index 00000000..9e92274a
--- /dev/null
+++ b/kig/modes/base_mode.cc
@@ -0,0 +1,160 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "base_mode.h"
+
+#include "popup.h"
+
+#include "../kig/kig_view.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_document.h"
+
+#include <qevent.h>
+#include <kcursor.h>
+
+BaseMode::BaseMode( KigPart& d )
+ : KigMode( d )
+{
+}
+
+BaseMode::~BaseMode()
+{
+}
+
+void BaseMode::leftClicked( QMouseEvent* e, KigWidget* v )
+{
+ // touch screens don't send a mouseMoved event before a click event,
+ // apparently, so we simulate it.
+ mouseMoved( e, v );
+
+ // get rid of text still showing...
+ v->updateCurPix();
+ v->updateWidget();
+
+ mplc = e->pos();
+ moco = mdoc.document().whatAmIOn( v->fromScreen( mplc ), *v );
+
+ if( moco.empty() )
+ {
+ // clicked on an empty spot --> we show the rectangle for
+ // selecting stuff...
+ dragRect( mplc, *v );
+ }
+ else
+ {
+ // the user clicked on some object.. --> this could either mean
+ // that he/she wants to select the object or that he wants to
+ // start moving it. We assume nothing here, we wait till he
+ // either moves some 4 pixels, or till he releases his mouse
+ // button in leftReleased() or mouseMoved()...
+ };
+}
+
+void BaseMode::leftMouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ if( !moco.empty() && ( mplc - e->pos() ).manhattanLength() > 3 )
+ dragObject( moco, mplc, *w,
+ ( e->state() & (ShiftButton | ControlButton ) ) != 0
+ );
+}
+
+void BaseMode::leftReleased( QMouseEvent* e, KigWidget* v )
+{
+ if( (mplc - e->pos()).manhattanLength() > 4 ) return;
+
+ ObjectHolder* o = 0;
+ bool keyCtrl = ( e->state() & ControlButton ) != 0;
+ bool keyShift = ( e->state() & ShiftButton ) != 0;
+ if ( ! moco.empty() )
+ {
+ if ( keyShift )
+ {
+ int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, moco );
+ if ( id >= 0 )
+ o = moco[id];
+ }
+ else
+ o = moco.front();
+ }
+ leftClickedObject( o, e->pos(), *v, keyCtrl );
+}
+
+void BaseMode::midClicked( QMouseEvent* e, KigWidget* v )
+{
+ // get rid of text still showing...
+ v->updateCurPix();
+ v->updateWidget();
+
+ mplc = e->pos();
+ moco = mdoc.document().whatAmIOn( v->fromScreen( e->pos() ), *v );
+}
+
+void BaseMode::midReleased( QMouseEvent* e, KigWidget* v )
+{
+ if( (e->pos() - mplc).manhattanLength() > 4 ) return;
+
+ midClicked( mplc, *v );
+}
+
+void BaseMode::rightClicked( QMouseEvent* e, KigWidget* w )
+{
+ // get rid of text still showing...
+ w->updateCurPix();
+ w->updateWidget();
+ // set a normal cursor...
+ w->setCursor( KCursor::arrowCursor() );
+
+ mplc = e->pos();
+ moco = mdoc.document().whatAmIOn( w->fromScreen( mplc ), *w );
+
+ rightClicked( moco, mplc, *w );
+}
+
+void BaseMode::mouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ std::vector<ObjectHolder*> os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w );
+ mouseMoved( os, e->pos(), *w, e->state() & Qt::ShiftButton );
+}
+
+void BaseMode::dragRect( const QPoint&, KigWidget& )
+{
+}
+
+void BaseMode::leftClickedObject( ObjectHolder*, const QPoint&,
+ KigWidget&, bool )
+{
+}
+
+void BaseMode::dragObject( const std::vector<ObjectHolder*>&, const QPoint&,
+ KigWidget&, bool )
+{
+}
+
+void BaseMode::enableActions()
+{
+ KigMode::enableActions();
+}
+
+std::vector<ObjectHolder*> BaseMode::oco()
+{
+ return moco;
+}
+
+QPoint BaseMode::pointLocation()
+{
+ return mplc;
+}
diff --git a/kig/modes/base_mode.h b/kig/modes/base_mode.h
new file mode 100644
index 00000000..2f89996f
--- /dev/null
+++ b/kig/modes/base_mode.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODE_BASE_MODE_H
+#define KIG_MODE_BASE_MODE_H
+
+#include "mode.h"
+
+#include <qpoint.h>
+#include <vector>
+
+class KigWidget;
+class KigDocument;
+class ObjectHolder;
+
+class BaseMode
+ : public KigMode
+{
+ QPoint mplc;
+ std::vector<ObjectHolder*> moco;
+
+ void leftClicked( QMouseEvent* e, KigWidget* v );
+ void leftMouseMoved( QMouseEvent*, KigWidget* );
+ void leftReleased( QMouseEvent* e, KigWidget* v );
+ void midClicked( QMouseEvent* e, KigWidget* v );
+ void midReleased( QMouseEvent* e, KigWidget* v );
+ void rightClicked( QMouseEvent*, KigWidget* );
+ void mouseMoved( QMouseEvent* e, KigWidget* v );
+
+protected:
+ void enableActions();
+
+ std::vector<ObjectHolder*> oco();
+ QPoint pointLocation();
+protected:
+
+ virtual void dragRect( const QPoint& p, KigWidget& w );
+ virtual void dragObject( const std::vector<ObjectHolder*>& os, const QPoint& pointClickedOn, KigWidget& w, bool ctrlOrShiftDown );
+ virtual void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown ) = 0;
+ virtual void midClicked( const QPoint& p, KigWidget& w ) = 0;
+ virtual void rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w ) = 0;
+ virtual void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftpressed ) = 0;
+
+protected:
+ BaseMode( KigPart& );
+ ~BaseMode();
+};
+
+#endif
diff --git a/kig/modes/construct_mode.cc b/kig/modes/construct_mode.cc
new file mode 100644
index 00000000..9618aded
--- /dev/null
+++ b/kig/modes/construct_mode.cc
@@ -0,0 +1,572 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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 "construct_mode.h"
+
+#include "../objects/object_factory.h"
+#include "../objects/object_drawer.h"
+#include "../objects/text_type.h"
+#include "../objects/text_imp.h"
+#include "../objects/bogus_imp.h"
+#include "../objects/point_imp.h"
+#include "../misc/argsparser.h"
+
+#include "../kig/kig_document.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../misc/object_constructor.h"
+#include "../misc/coordinate_system.h"
+#include "../misc/kigpainter.h"
+#include "../misc/calcpaths.h"
+
+#include "popup.h"
+
+#include <kcursor.h>
+#include <kaction.h>
+
+#include <algorithm>
+#include <functional>
+
+static void redefinePoint( ObjectTypeCalcer* mpt, const Coordinate& c, KigDocument& doc, const KigWidget& w )
+{
+ ObjectFactory::instance()->redefinePoint( mpt, c, doc, w );
+ mpt->calc( doc );
+}
+
+BaseConstructMode::BaseConstructMode( KigPart& d )
+ : BaseMode( d )
+{
+ mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate( 0, 0 ) );
+ mpt->calc( d.document() );
+ mcursor = ObjectFactory::instance()->cursorPointCalcer( Coordinate( 0, 0 ) );
+ mcursor->calc( d.document() );
+// mcursorholder = new ObjectHolder( mcursor );
+}
+
+BaseConstructMode::~BaseConstructMode()
+{
+ delete mcursor;
+// delete mcursorholder;
+}
+
+void BaseConstructMode::leftReleased( QMouseEvent* e, KigWidget* v )
+{
+ if( (pointLocation() - e->pos()).manhattanLength() > 4 ) return;
+
+ ObjectHolder* o = 0;
+ bool keyCtrlOrShift = ( e->state() & ( ControlButton | ShiftButton) ) != 0;
+ std::vector<ObjectHolder*> moco = oco();
+ if ( ! moco.empty() )
+ {
+ std::vector<ObjectHolder*> goodargs;
+ if ( !moco.empty() )
+ {
+ std::vector<ObjectHolder*>::const_iterator it;
+ std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
+ for ( std::vector<ObjectHolder*>::const_iterator i = moco.begin(); i != moco.end(); ++i )
+ {
+ it = std::find( mparents.begin(), mparents.end(), *i );
+ bool newdup =
+ ( it == mparents.end() ) ||
+ isAlreadySelectedOK( testargs, it - mparents.begin() );
+ if ( newdup )
+ {
+ testargs.push_back( ( *i )->calcer() );
+ if ( wantArgs( testargs, mdoc.document(), *v ) )
+ goodargs.push_back( *i );
+ testargs.pop_back();
+ }
+ }
+ int id = ObjectChooserPopup::getObjectFromList( e->pos(), v, goodargs );
+ if ( id >= 0 )
+ o = goodargs[id];
+ }
+ }
+ leftClickedObject( o, e->pos(), *v, keyCtrlOrShift );
+ KigMode::leftReleased( e, v );
+}
+
+void BaseConstructMode::leftClickedObject(
+ ObjectHolder* o, const QPoint& p, KigWidget& w, bool )
+{
+ std::vector<ObjectHolder*>::iterator it = std::find( mparents.begin(), mparents.end(), o );
+ std::vector<ObjectCalcer*> nargs = getCalcers( mparents );
+//
+// mp: duplicationchecked controls whether the arguments list is
+// free of duplications or if a duplication is safe (asking this to
+// the Constructor class through the "isAlreadySelectedOK" method).
+//
+ bool duplicationchecked =
+ ( it == mparents.end() ) ||
+ isAlreadySelectedOK( nargs, it - mparents.begin() );
+ if ( o && duplicationchecked )
+ {
+ nargs.push_back( o->calcer() );
+ if ( wantArgs( nargs, mdoc.document(), w ) )
+ {
+ selectObject( o, w );
+ return;
+ }
+ }
+
+ nargs = getCalcers( mparents );
+ nargs.push_back( mpt.get() );
+ if ( wantArgs( nargs, mdoc.document(), w ) )
+ {
+ // add mpt to the document..
+ ObjectHolder* n = new ObjectHolder( mpt.get() );
+ mdoc.addObject( n );
+ selectObject( n, w );
+ // get a new mpt for our further use..
+ mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
+ mpt->calc( mdoc.document() );
+ return;
+ }
+
+ nargs = getCalcers( mparents );
+ nargs.push_back( mcursor );
+
+ if ( wantArgs( nargs, mdoc.document(), w ) )
+ {
+ // DON'T add mpt to the document..
+ // the objectholder has been constructed once and for all
+ // when entering construction mode, and delete in the
+ // destructor.
+ ObjectHolder* n = new ObjectHolder( mcursor );
+ selectObject( n, w );
+ mcursor = ObjectFactory::instance()->cursorPointCalcer( w.fromScreen( p ) );
+// mcursor = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
+ mcursor->calc( mdoc.document() );
+ delete n;
+ }
+}
+
+void BaseConstructMode::midClicked( const QPoint& p, KigWidget& w )
+{
+ std::vector<ObjectCalcer*> args = getCalcers( mparents );
+ args.push_back( mpt.get() );
+ if ( wantArgs( args, mdoc.document(), w ) )
+ {
+ ObjectHolder* n = new ObjectHolder( mpt.get() );
+ mdoc.addObject( n );
+
+ selectObject( n, w );
+
+ mpt = ObjectFactory::instance()->sensiblePointCalcer( w.fromScreen( p ), mdoc.document(), w );
+ mpt->calc( mdoc.document() );
+ }
+}
+
+void BaseConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const QPoint&, KigWidget& )
+{
+ // TODO ?
+}
+
+void BaseConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p,
+ KigWidget& w, bool shiftpressed )
+{
+ mdoc.emitStatusBarText( selectStatement( getCalcers( mparents ), w ) );
+
+ w.updateCurPix();
+ KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ Coordinate ncoord = w.fromScreen( p );
+ if ( shiftpressed )
+ ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
+
+ redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
+ mcursor->move( ncoord, mdoc.document() );
+ mcursor->calc( mdoc.document() );
+
+ std::vector<ObjectCalcer*> args = getCalcers( mparents );
+ bool duplicationchecked = false;
+ std::vector<ObjectHolder*> goodargs;
+ if ( ! os.empty() )
+ {
+ std::vector<ObjectHolder*>::const_iterator it;
+ std::vector<ObjectCalcer*> testargs = getCalcers( mparents );
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ {
+ it = std::find( mparents.begin(), mparents.end(), *i );
+ bool newdup =
+ ( it == mparents.end() ) ||
+ isAlreadySelectedOK( args, it - mparents.begin() );
+ if ( newdup )
+ {
+ testargs.push_back( ( *i )->calcer() );
+ if ( wantArgs( testargs, mdoc.document(), w ) )
+ goodargs.push_back( *i );
+ testargs.pop_back();
+ }
+ duplicationchecked |= newdup;
+ }
+ }
+ bool calcnow = ( goodargs.size() == 1 ) || ( ( goodargs.size() > 0 ) && ( goodargs.front()->imp()->inherits( PointImp::stype() ) ) );
+ if ( calcnow )
+ {
+ args.push_back( goodargs.front()->calcer() );
+ }
+
+ if ( !os.empty() && duplicationchecked && calcnow )
+ {
+ handlePrelim( args, p, pter, w );
+
+ w.setCursor( KCursor::handCursor() );
+ }
+ else
+ {
+ std::vector<ObjectCalcer*> args = getCalcers( mparents );
+ args.push_back( mpt.get() );
+ std::vector<ObjectCalcer*> argscursor = getCalcers( mparents );
+ argscursor.push_back( mcursor );
+ bool text = true;
+ if ( wantArgs( args, mdoc.document(), w ) )
+ {
+ ObjectDrawer d;
+ d.draw( *mpt->imp(), pter, true );
+
+ handlePrelim( args, p, pter, w );
+
+ w.setCursor( KCursor::handCursor() );
+ }
+ else if ( wantArgs( argscursor, mdoc.document(), w ) )
+ {
+ ObjectDrawer d;
+// d.draw( *mcursor->imp(), pter, true );
+
+ handlePrelim( argscursor, p, pter, w );
+
+ w.setCursor( KCursor::crossCursor() );
+ }
+ else
+ {
+ w.setCursor( KCursor::arrowCursor() );
+ text = false;
+ }
+ if ( !text && ( goodargs.size() > 1 ) )
+ {
+ QString strwhich = i18n( "Which object?" );
+ mdoc.emitStatusBarText( strwhich );
+
+ QPoint textloc = p;
+ textloc.setX( textloc.x() + 15 );
+ pter.drawTextStd( textloc, strwhich );
+
+ w.setCursor( KCursor::handCursor() );
+ }
+ }
+ w.updateWidget( pter.overlay() );
+}
+
+void BaseConstructMode::selectObject( ObjectHolder* o, KigWidget& w )
+{
+ mparents.push_back( o );
+ std::vector<ObjectCalcer*> args = getCalcers( mparents );
+
+ if ( wantArgs( args, mdoc.document(), w ) == ArgsParser::Complete )
+ {
+ handleArgs( args, w );
+ };
+
+ w.redrawScreen( mparents );
+}
+
+PointConstructMode::PointConstructMode( KigPart& d )
+ : BaseMode( d )
+{
+ // we add the data objects to the document cause
+ // ObjectFactory::redefinePoint does that too, and this way, we can
+ // depend on them already being known by the doc when we add the
+ // mpt..
+ mpt = ObjectFactory::instance()->fixedPointCalcer( Coordinate() );
+ mpt->calc( d.document() );
+
+ mdoc.emitStatusBarText( i18n( "Click the location where you want to place the new point, or the curve that you want to attach it to..." ) );
+}
+
+PointConstructMode::~PointConstructMode()
+{
+}
+
+void PointConstructMode::leftClickedObject(
+ ObjectHolder*, const QPoint&, KigWidget& w, bool )
+{
+ mdoc.addObject( new ObjectHolder( mpt.get() ) );
+ w.redrawScreen( std::vector<ObjectHolder*>() );
+
+ mdoc.emitStatusBarText( QString::null );
+ mdoc.doneMode( this );
+}
+
+void PointConstructMode::midClicked( const QPoint& p, KigWidget& w )
+{
+ leftClickedObject( 0, p, w, true );
+}
+
+void PointConstructMode::rightClicked( const std::vector<ObjectHolder*>&, const QPoint&,
+ KigWidget& )
+{
+ // TODO ?
+}
+
+void PointConstructMode::mouseMoved(
+ const std::vector<ObjectHolder*>&,
+ const QPoint& p,
+ KigWidget& w,
+ bool shiftpressed )
+{
+ w.updateCurPix();
+ KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ Coordinate ncoord = w.fromScreen( p );
+ if ( shiftpressed )
+ ncoord = mdoc.document().coordinateSystem().snapToGrid( ncoord, w );
+
+ redefinePoint( mpt.get(), ncoord, mdoc.document(), w );
+
+ ObjectDrawer d;
+ d.draw( *mpt->imp(), pter, true );
+ w.setCursor( KCursor::blankCursor() );
+
+ w.updateWidget( pter.overlay() );
+}
+
+void BaseConstructMode::enableActions()
+{
+ BaseMode::enableActions();
+
+ mdoc.aCancelConstruction->setEnabled( true );
+}
+
+void BaseConstructMode::cancelConstruction()
+{
+ finish();
+}
+
+void PointConstructMode::enableActions()
+{
+ BaseMode::enableActions();
+
+ mdoc.aCancelConstruction->setEnabled( true );
+}
+
+void PointConstructMode::cancelConstruction()
+{
+ mdoc.doneMode( this );
+}
+
+void BaseConstructMode::selectObjects( const std::vector<ObjectHolder*>& os, KigWidget& w )
+{
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ {
+ std::vector<ObjectCalcer*> args = getCalcers( mparents );
+ assert( wantArgs( args, mdoc.document(), w ) != ArgsParser::Complete );
+ selectObject( *i, w );
+ };
+}
+
+void ConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& args, const QPoint& p, KigPainter& pter, KigWidget& w )
+{
+ // set the text next to the arrow cursor like in modes/normal.cc
+ QPoint textloc = p;
+ textloc.setX( textloc.x() + 15 );
+
+ mctor->handlePrelim( pter, args, mdoc.document(), w );
+
+ QString o = mctor->useText( *args.back(), args, mdoc.document(), w );
+ pter.drawTextStd( textloc, o );
+}
+
+int ConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>& os,
+ const int& pos )
+{
+ return mctor->isAlreadySelectedOK( os, pos );
+}
+
+int ConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument& d, KigWidget& w )
+{
+ return mctor->wantArgs( os, d, w );
+}
+
+void BaseConstructMode::finish()
+{
+ mdoc.doneMode( this );
+}
+
+ConstructMode::ConstructMode( KigPart& d, const ObjectConstructor* ctor )
+ : BaseConstructMode( d ), mctor( ctor )
+{
+}
+
+ConstructMode::~ConstructMode()
+{
+}
+
+// does a test result have a frame by default ?
+static const bool test_has_frame_dflt = true;
+
+void TestConstructMode::handlePrelim( const std::vector<ObjectCalcer*>& os, const QPoint& p, KigPainter& pter, KigWidget& w )
+{
+ Args args;
+ std::transform( os.begin(), os.end(), std::back_inserter( args ),
+ std::mem_fun( &ObjectCalcer::imp ) );
+
+ // usetext
+ QString usetext = i18n( mtype->argsParser().usetext( args.back(), args ).c_str() );
+ QPoint textloc = p;
+ textloc.setX( textloc.x() + 15 );
+ pter.drawTextStd( textloc, usetext );
+
+ // test result
+ ObjectImp* data = mtype->calc( args, mdoc.document() );
+ if ( ! data->valid() ) return;
+ assert( data->inherits( TestResultImp::stype() ) );
+ QString outputtext = static_cast<TestResultImp*>( data )->data();
+ TextImp ti( outputtext, w.fromScreen( p + QPoint( - 40, 30 ) ), test_has_frame_dflt );
+ ti.draw( pter );
+
+ delete data;
+}
+
+TestConstructMode::TestConstructMode( KigPart& d, const ArgsParserObjectType* type )
+ : BaseConstructMode( d ), mtype( type )
+{
+}
+
+TestConstructMode::~TestConstructMode()
+{
+}
+
+void ConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w )
+{
+ mctor->handleArgs( args, mdoc, w );
+ finish();
+}
+
+int TestConstructMode::isAlreadySelectedOK( const std::vector<ObjectCalcer*>&,
+ const int& )
+{
+ return false;
+}
+
+int TestConstructMode::wantArgs( const std::vector<ObjectCalcer*>& os, KigDocument&, KigWidget& )
+{
+ return mtype->argsParser().check( os );
+}
+
+void TestConstructMode::handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& )
+{
+ mresult = new ObjectTypeCalcer( mtype, args );
+ mresult->calc( mdoc.document() );
+ mdoc.emitStatusBarText( i18n( "Now select the location for the result label." ) );
+}
+
+void TestConstructMode::leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown )
+{
+ if ( mresult ) {
+ QPoint qloc = p + QPoint( -40, 0 );
+ Coordinate loc = w.fromScreen( qloc );
+
+ std::vector<ObjectCalcer*> parents;
+ parents.push_back( new ObjectConstCalcer( new IntImp( test_has_frame_dflt ) ) );
+ parents.push_back( new ObjectConstCalcer( new PointImp( loc ) ) );
+ parents.push_back( new ObjectConstCalcer( new StringImp( QString::fromLatin1( "%1" ) ) ) );
+ assert( mresult->imp()->inherits( TestResultImp::stype() ) );
+ parents.push_back(
+ new ObjectPropertyCalcer(
+ mresult.get(), mresult->imp()->propertiesInternalNames().findIndex( "test-result" ) ) );
+ parents.back()->calc( mdoc.document() );
+
+ ObjectCalcer* ret = new ObjectTypeCalcer( TextType::instance(), parents );
+ ret->calc( mdoc.document() );
+ mdoc.addObject( new ObjectHolder( ret ) );
+
+ w.unsetCursor();
+ mdoc.emitStatusBarText( QString::null );
+
+ finish();
+ }
+ else
+ BaseConstructMode::leftClickedObject( o, p, w, ctrlOrShiftDown );
+}
+
+void TestConstructMode::midClicked( const QPoint& p, KigWidget& w )
+{
+ if ( mresult ) {
+ // nothing to be done here, really
+ }
+ else
+ BaseConstructMode::midClicked( p, w );
+}
+
+void TestConstructMode::rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w )
+{
+ if ( mresult ) {
+ // nothing to be done here, really
+ }
+ else
+ BaseConstructMode::rightClicked( oco, p, w );
+}
+
+void TestConstructMode::mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftPressed )
+{
+ if ( mresult ) {
+ w.setCursor( KCursor::blankCursor() );
+
+ w.updateCurPix();
+ KigPainter pter( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ QPoint qloc = p + QPoint( -40, 0 );
+ Coordinate loc = w.fromScreen( qloc );
+ assert( dynamic_cast<const TestResultImp*>( mresult->imp() ) );
+ TextImp ti( static_cast<const TestResultImp*>( mresult->imp() )->data(), loc, test_has_frame_dflt );
+ ObjectDrawer d;
+ d.draw( ti, pter, false );
+
+
+ w.updateWidget( pter.overlay() );
+ }
+ else
+ BaseConstructMode::mouseMoved( os, p, w, shiftPressed );
+}
+
+QString ConstructMode::selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w )
+{
+ return mctor->selectStatement( args, mdoc.document(), w );
+}
+
+QString TestConstructMode::selectStatement( const std::vector<ObjectCalcer*>& sel, const KigWidget& )
+{
+ using namespace std;
+ Args args;
+ transform( sel.begin(), sel.end(), back_inserter( args ), mem_fun( &ObjectCalcer::imp ) );
+
+ std::string ret = mtype->argsParser().selectStatement( args );
+ if ( ret.empty() ) return QString::null;
+ return i18n( ret.c_str() );
+}
+
+void PointConstructMode::redrawScreen( KigWidget* w )
+{
+ w->redrawScreen( std::vector<ObjectHolder*>() );
+}
+
+void BaseConstructMode::redrawScreen( KigWidget* w )
+{
+ w->redrawScreen( std::vector<ObjectHolder*>() );
+}
diff --git a/kig/modes/construct_mode.h b/kig/modes/construct_mode.h
new file mode 100644
index 00000000..fa1be86e
--- /dev/null
+++ b/kig/modes/construct_mode.h
@@ -0,0 +1,154 @@
+// Copyright (C) 2003 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODES_CONSTRUCT_MODE_H
+#define KIG_MODES_CONSTRUCT_MODE_H
+
+#include "base_mode.h"
+
+#include "../objects/object_calcer.h"
+
+class ArgsParserObjectType;
+class ObjectConstructor;
+class ObjectCalcer;
+
+class PointConstructMode
+ : public BaseMode
+{
+ /**
+ * this is the point that we move around, for the user to add
+ * somewhere..
+ */
+ ObjectTypeCalcer::shared_ptr mpt;
+public:
+ PointConstructMode( KigPart& d );
+ ~PointConstructMode();
+protected:
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void midClicked( const QPoint& p, KigWidget& w );
+ void rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftpressed );
+
+ void enableActions();
+ void cancelConstruction();
+
+ void redrawScreen( KigWidget* );
+};
+
+class BaseConstructMode
+ : public BaseMode
+{
+ /**
+ * this is the point that we move around, in case the user wants to
+ * add a point somewhere..
+ */
+ ObjectTypeCalcer::shared_ptr mpt;
+ /**
+ * mp: this point always follows the cursor
+ *
+ * IMPORTANT: this Calcer must NEVER be added to the document, since
+ * its is used in constructors that need more input from the user
+ * to decide parameters of the constructed object that will be fixed
+ * afterwards (like the number of sides of a regular polygon)
+ */
+ ObjectTypeCalcer* mcursor;
+ // we also allocate here the corresponding objectholder, since the
+ // only sensible place where to deallocate it is in the destructor
+ // of this class
+// ObjectHolder* mcursorholder;
+ std::vector<ObjectHolder*> mparents;
+
+ void leftReleased( QMouseEvent* e, KigWidget* v );
+
+public:
+ void selectObject( ObjectHolder* o, KigWidget& w );
+ void selectObjects( const std::vector<ObjectHolder*>& os, KigWidget& w );
+ virtual ~BaseConstructMode();
+protected:
+ BaseConstructMode( KigPart& d );
+protected:
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void midClicked( const QPoint& p, KigWidget& w );
+ void rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftpressed );
+
+ void enableActions();
+ void cancelConstruction();
+ void finish();
+
+protected:
+ virtual void handlePrelim( const std::vector<ObjectCalcer*>& os, const QPoint& p, KigPainter&, KigWidget& w ) = 0;
+ virtual QString selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w ) = 0;
+ virtual int isAlreadySelectedOK( const std::vector<ObjectCalcer*>&, const int& ) = 0;
+ virtual int wantArgs( const std::vector<ObjectCalcer*>&, KigDocument& d, KigWidget& w ) = 0;
+ virtual void handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w ) = 0;
+
+ void redrawScreen( KigWidget* );
+};
+
+class ConstructMode
+ : public BaseConstructMode
+{
+ const ObjectConstructor* mctor;
+public:
+ ConstructMode( KigPart& d, const ObjectConstructor* ctor );
+ ~ConstructMode();
+
+ void handlePrelim( const std::vector<ObjectCalcer*>& os, const QPoint& p, KigPainter&, KigWidget& w );
+ QString selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w );
+ int isAlreadySelectedOK( const std::vector<ObjectCalcer*>&, const int& );
+ int wantArgs( const std::vector<ObjectCalcer*>&, KigDocument& d, KigWidget& w );
+ void handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w );
+};
+
+/**
+ * This class constructs a test object. It has special needs over
+ * ConstructMode because first the arguments need to be chosen, and
+ * then the location for the resulting TextImp needs to be chosen. It
+ * also needs special code for the drawPrelim and wantArgs code.
+ *
+ * Therefore, we inherit from BaseConstructMode, and override the
+ * event callbacks, so that this mode behaves like a
+ * BaseConstructMode, until handleArgs is called. After that, mresult
+ * is no longer 0, and then the mode behaves in its own way, allowing
+ * the user to choose a location for the new label object.
+ */
+class TestConstructMode
+ : public BaseConstructMode
+{
+ const ArgsParserObjectType* mtype;
+ ObjectCalcer::shared_ptr mresult;
+public:
+ TestConstructMode( KigPart& d, const ArgsParserObjectType* type );
+ ~TestConstructMode();
+
+ void handlePrelim( const std::vector<ObjectCalcer*>& os, const QPoint& p, KigPainter&, KigWidget& w );
+ QString selectStatement( const std::vector<ObjectCalcer*>& args, const KigWidget& w );
+ int isAlreadySelectedOK( const std::vector<ObjectCalcer*>&, const int& );
+ int wantArgs( const std::vector<ObjectCalcer*>&, KigDocument& d, KigWidget& w );
+ void handleArgs( const std::vector<ObjectCalcer*>& args, KigWidget& w );
+
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void midClicked( const QPoint& p, KigWidget& w );
+ void rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftpressed );
+};
+
+#endif
diff --git a/kig/modes/dragrectmode.cc b/kig/modes/dragrectmode.cc
new file mode 100644
index 00000000..a3c8c033
--- /dev/null
+++ b/kig/modes/dragrectmode.cc
@@ -0,0 +1,180 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "dragrectmode.h"
+
+#include "../kig/kig_document.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../misc/kigpainter.h"
+
+#include <qevent.h>
+#include <qglobal.h>
+#include <kaction.h>
+
+DragRectMode::DragRectMode( const QPoint& start, KigPart& d, KigWidget& w )
+ : KigMode( d ), mstart( start ), mnc( true ), mstartselected( true ),
+ mcancelled( false )
+{
+ moved( start, w );
+}
+
+DragRectMode::DragRectMode( KigPart& d, KigWidget& w )
+ : KigMode( d ), mnc( true ), mstartselected( false ),
+ mcancelled( false )
+{
+ w.updateCurPix();
+ w.updateWidget();
+}
+
+void DragRectMode::moved( const QPoint& p, KigWidget& w )
+{
+ // update the rect...
+ w.updateCurPix();
+ std::vector<QRect> overlay;
+ if ( mstartselected )
+ {
+ KigPainter pt( w.screenInfo(), &w.curPix, mdoc.document() );
+ pt.drawFilledRect( QRect( p, mstart ) );
+ overlay = pt.overlay();
+ };
+ w.updateWidget( overlay );
+}
+
+void DragRectMode::released( const QPoint& p, KigWidget& w, bool nc )
+{
+ if ( mstartselected )
+ {
+ mrect = w.fromScreen( QRect( mstart, p ) );
+ mret = mdoc.document().whatIsInHere( mrect, w );
+ mnc = nc;
+
+ mdoc.doneMode( this );
+ };
+}
+
+void DragRectMode::enableActions()
+{
+ KigMode::enableActions();
+
+ mdoc.aCancelConstruction->setEnabled( true );
+}
+
+std::vector<ObjectHolder*> DragRectMode::ret() const
+{
+ return mret;
+}
+
+bool DragRectMode::needClear() const
+{
+ return mnc;
+}
+
+void DragRectMode::moved( QMouseEvent* e, KigWidget& w )
+{
+ moved( e->pos(), w );
+}
+
+void DragRectMode::released( QMouseEvent* e, KigWidget& w )
+{
+ released( e->pos(), w, ! ( e->state() & ( ControlButton | ShiftButton ) ) );
+}
+
+DragRectMode::~DragRectMode()
+{
+}
+
+void DragRectMode::mouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ moved( e, *w );
+}
+
+void DragRectMode::leftMouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ moved( e, *w );
+}
+
+void DragRectMode::midMouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ moved( e, *w );
+}
+
+void DragRectMode::rightMouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ moved( e, *w );
+}
+
+void DragRectMode::leftReleased( QMouseEvent* e, KigWidget* w )
+{
+ released( e, *w );
+}
+
+void DragRectMode::midReleased( QMouseEvent* e, KigWidget* w )
+{
+ released( e, *w );
+}
+
+void DragRectMode::rightReleased( QMouseEvent* e, KigWidget* w )
+{
+ released( e, *w );
+}
+
+Rect DragRectMode::rect() const
+{
+ return mrect;
+}
+
+void DragRectMode::clicked( const QMouseEvent* e, KigWidget& w )
+{
+ clicked( e->pos(), w );
+}
+
+void DragRectMode::leftClicked( QMouseEvent* e, KigWidget* w )
+{
+ clicked( e, *w );
+}
+
+void DragRectMode::midClicked( QMouseEvent* e, KigWidget* w )
+{
+ clicked( e, *w );
+}
+
+void DragRectMode::rightClicked( QMouseEvent* e, KigWidget* w )
+{
+ clicked( e, *w );
+}
+
+void DragRectMode::clicked( const QPoint& p, KigWidget& )
+{
+ if ( !mstartselected )
+ {
+ mstartselected = true;
+ mstart = p;
+ };
+}
+
+bool DragRectMode::cancelled() const
+{
+ return mcancelled;
+}
+
+void DragRectMode::cancelConstruction()
+{
+ mcancelled = true;
+ mdoc.doneMode( this );
+}
+
diff --git a/kig/modes/dragrectmode.h b/kig/modes/dragrectmode.h
new file mode 100644
index 00000000..29f92139
--- /dev/null
+++ b/kig/modes/dragrectmode.h
@@ -0,0 +1,104 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+
+#ifndef KIG_MODES_DRAGRECTMODE_H
+#define KIG_MODES_DRAGRECTMODE_H
+
+#include "mode.h"
+
+#include "../misc/rect.h"
+
+#include <qpoint.h>
+#include <vector>
+
+class ObjectHolder;
+
+/**
+ * DragRectMode is a mode that provides a rect for selecting the
+ * objects inside it. Here's an example of how to use it
+ * \code
+ * DragRectMode d( e->pos(), document, widget );
+ * mDoc.runMode( &d );
+ * Objects sel = d.ret();
+ * \endcode
+ */
+class DragRectMode
+ : public KigMode
+{
+ QPoint mstart;
+ std::vector<ObjectHolder*> mret;
+ Rect mrect;
+ bool mnc;
+ bool mstartselected;
+ bool mcancelled;
+private:
+ void clicked( const QPoint& p, KigWidget& w );
+ void clicked( const QMouseEvent* e, KigWidget& w );
+ void released( const QPoint& p, KigWidget& w, bool nc );
+ void released( QMouseEvent* e, KigWidget& w );
+ void moved( const QPoint& p, KigWidget& w );
+ void moved( QMouseEvent*, KigWidget& w );
+
+ void leftClicked( QMouseEvent*, KigWidget* );
+ void leftMouseMoved( QMouseEvent*, KigWidget* );
+ void leftReleased( QMouseEvent*, KigWidget* );
+ void midClicked( QMouseEvent*, KigWidget* );
+ void midMouseMoved( QMouseEvent*, KigWidget* );
+ void midReleased( QMouseEvent*, KigWidget* );
+ void rightClicked( QMouseEvent*, KigWidget* );
+ void rightMouseMoved( QMouseEvent*, KigWidget* );
+ void rightReleased( QMouseEvent*, KigWidget* );
+ void mouseMoved( QMouseEvent*, KigWidget* );
+
+ void cancelConstruction();
+
+ void enableActions();
+
+public:
+ DragRectMode( const QPoint& start, KigPart& d, KigWidget& w );
+ DragRectMode( KigPart& d, KigWidget& w );
+ ~DragRectMode();
+
+ /**
+ * this returns the selected objects..
+ */
+ std::vector<ObjectHolder*> ret() const;
+
+ /**
+ * this returns the selected rect..
+ */
+ Rect rect() const;
+
+ /**
+ * this returns false if the control or shift button were pressed
+ * when the mouse button was released, and true otherwise. This is
+ * because the user expects us to not clear the selection before
+ * adding the newly selected objects if (s)he pressed control or
+ * shift..
+ */
+ bool needClear() const;
+
+ /**
+ * whether the user cancelled the rect mode.. If this returns true,
+ * all the other return data above will be in undefined state, so
+ * first check this function's result..
+ */
+ bool cancelled() const;
+};
+
+#endif
diff --git a/kig/modes/edittype.cc b/kig/modes/edittype.cc
new file mode 100644
index 00000000..8c6b538f
--- /dev/null
+++ b/kig/modes/edittype.cc
@@ -0,0 +1,107 @@
+/**
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2004 Dominique Devriese <devriese@kde.org>
+ Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
+
+ 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 "edittype.h"
+#include "edittype.moc"
+
+#include <kapplication.h>
+#include <kicondialog.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+EditType::EditType( QWidget* parent, QString name, QString desc, QString icon )
+ : EditTypeBase( parent, "edittype", true ), mname( name ), mdesc( desc ), micon( icon )
+{
+ // improving GUI look'n'feel...
+ buttonHelp->setGuiItem( KStdGuiItem::help() );
+ buttonOk->setGuiItem( KStdGuiItem::ok() );
+ buttonCancel->setGuiItem( KStdGuiItem::cancel() );
+
+ editName->setText( mname );
+ editDescription->setText( mdesc );
+ typeIcon->setIcon( !micon.isEmpty() ? micon : "gear" );
+}
+
+EditType::~EditType()
+{
+}
+
+void EditType::helpSlot()
+{
+ kapp->invokeHelp( QString::fromLatin1( "working-with-types" ),
+ QString::fromLatin1( "kig" ) );
+}
+
+void EditType::okSlot()
+{
+ QString tmp = editName->text();
+ if ( tmp.isEmpty() )
+ {
+ KMessageBox::information( this, i18n( "The name of the macro can not be empty." ) );
+ return;
+ }
+
+ bool namechanged = false;
+ bool descchanged = false;
+ bool iconchanged = false;
+ if ( tmp != mname )
+ {
+ mname = tmp;
+ namechanged = true;
+ }
+ tmp = editDescription->text();
+ if ( tmp != mdesc )
+ {
+ mdesc = tmp;
+ descchanged = true;
+ }
+ tmp = typeIcon->icon();
+ if ( tmp != micon )
+ {
+ micon = tmp;
+ iconchanged = true;
+ }
+ done( namechanged || descchanged || iconchanged );
+}
+
+void EditType::cancelSlot()
+{
+ done( 0 );
+}
+
+const QString EditType::name() const
+{
+ return mname;
+}
+
+const QString EditType::description() const
+{
+ return mdesc;
+}
+
+const QString EditType::icon() const
+{
+ return micon;
+}
diff --git a/kig/modes/edittype.h b/kig/modes/edittype.h
new file mode 100644
index 00000000..c6530df5
--- /dev/null
+++ b/kig/modes/edittype.h
@@ -0,0 +1,48 @@
+// This file is part of Kig, a KDE program for Interactive Geometry...
+// Copyright (C) 2004 Dominique Devriese <devriese@kde.org>
+// Copyright (C) 2004 Pino Toscano <toscano.pino@tiscali.it>
+
+// 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.
+
+#ifndef KIG_MODES_EDITTYPE_H
+#define KIG_MODES_EDITTYPE_H
+
+#include "edittypebase.h"
+
+/**
+ * Simply dialog that allow the user the editing of a macro type...
+ */
+class EditType : public EditTypeBase
+{
+ Q_OBJECT
+
+ QString mname;
+ QString mdesc;
+ QString micon;
+public:
+ EditType( QWidget* parent, QString name = QString::null, QString desc = QString::null, QString icon = QString::null );
+ ~EditType();
+ const QString name() const;
+ const QString description() const;
+ const QString icon() const;
+
+public slots:
+ void helpSlot();
+ void okSlot();
+ void cancelSlot();
+};
+
+#endif
diff --git a/kig/modes/edittypebase.ui b/kig/modes/edittypebase.ui
new file mode 100644
index 00000000..0dc8129d
--- /dev/null
+++ b/kig/modes/edittypebase.ui
@@ -0,0 +1,287 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>EditTypeBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>EditTypeBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>481</width>
+ <height>142</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Edit Type</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label15</cstring>
+ </property>
+ <property name="text">
+ <string>Here you can modify the name, the description and the icon of this macro type.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout8</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label16</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>editName</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can edit the name of the current macro type.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>label17</cstring>
+ </property>
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>editDescription</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can edit the description of the current macro type. This field is optional, so you can also leave this empty: if you do so, then your macro type will have no description.</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout23</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KIconButton">
+ <property name="name">
+ <cstring>typeIcon</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Use this button to change the icon of the current macro type.</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout24</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>buttonHelp</sender>
+ <signal>clicked()</signal>
+ <receiver>EditTypeBase</receiver>
+ <slot>helpSlot()</slot>
+ </connection>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>EditTypeBase</receiver>
+ <slot>okSlot()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>EditTypeBase</receiver>
+ <slot>cancelSlot()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot>helpSlot()</slot>
+ <slot>okSlot()</slot>
+ <slot>cancelSlot()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+ <includehint>kicondialog.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>
diff --git a/kig/modes/label.cc b/kig/modes/label.cc
new file mode 100644
index 00000000..cd726918
--- /dev/null
+++ b/kig/modes/label.cc
@@ -0,0 +1,589 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "label.h"
+#include "normal.h"
+
+#include "textlabelwizard.h"
+#include "linkslabel.h"
+
+#include "../kig/kig_commands.h"
+#include "../kig/kig_document.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../misc/common.h"
+#include "../misc/kigpainter.h"
+#include "../objects/bogus_imp.h"
+#include "../objects/curve_imp.h"
+#include "../objects/object_factory.h"
+#include "../objects/point_imp.h"
+#include "../objects/text_imp.h"
+#include "../objects/text_type.h"
+
+#include <kcursor.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <klocale.h>
+#include <qtextedit.h>
+#include <kdebug.h>
+#include <kiconloader.h>
+#include <qregexp.h>
+#include <qpopupmenu.h>
+#include <qcheckbox.h>
+
+#include <algorithm>
+#include <functional>
+
+class TextLabelModeBase::Private
+{
+public:
+ // point last clicked..
+ QPoint plc;
+ // the currently selected coordinate
+ Coordinate mcoord;
+ // the possible parent object that defines the location of the label..
+ ObjectCalcer* locationparent;
+
+ // the text is only kept in the text input widget, not here
+ // QString mtext;
+
+ // the property objects we'll be using as args, we keep a reference
+ // to them in the args object, and keep a pointer to them ( or 0 )
+ // in the correct order in args ( separately, because we can't use
+ // the order of the parents of a ReferenceObject, and certainly
+ // can't give 0 as a parent..
+ argvect args;
+
+ // if we're ReallySelectingArgs, then this var points to the arg
+ // we're currently selecting...
+ int mwaaws;
+
+ // last percent count...
+ uint lpc;
+
+ TextLabelWizard* wiz;
+
+ // What Are We Doing
+ wawdtype mwawd;
+};
+
+TextLabelModeBase::~TextLabelModeBase()
+{
+ delete d->wiz;
+ delete d;
+}
+
+TextLabelModeBase::TextLabelModeBase( KigPart& doc )
+ : KigMode( doc ), d( new Private )
+{
+ d->locationparent = 0;
+ d->lpc = 0;
+ d->mwawd = SelectingLocation;
+ d->wiz = new TextLabelWizard( doc.widget(), this );
+}
+
+void TextLabelModeBase::leftClicked( QMouseEvent* e, KigWidget* )
+{
+ d->plc = e->pos();
+ switch( d->mwawd )
+ {
+ case RequestingText:
+ case SelectingArgs:
+ d->wiz->raise();
+ d->wiz->setActiveWindow();
+ break;
+ default:
+ break;
+ };
+}
+
+void TextLabelModeBase::leftReleased( QMouseEvent* e, KigWidget* v )
+{
+ switch( d->mwawd )
+ {
+ case SelectingLocation:
+ {
+ if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) return;
+ setCoordinate( v->fromScreen( d->plc ) );
+ break;
+ }
+ case RequestingText:
+ case SelectingArgs:
+ d->wiz->raise();
+ d->wiz->setActiveWindow();
+ break;
+ case ReallySelectingArgs:
+ {
+ if ( ( d->plc - e->pos() ).manhattanLength() > 4 ) break;
+ std::vector<ObjectHolder*> os = mdoc.document().whatAmIOn( v->fromScreen( d->plc ), *v );
+ if ( os.empty() ) break;
+ ObjectHolder* o = os[0];
+ QPopupMenu* p = new QPopupMenu( v, "text_label_select_arg_popup" );
+ p->insertItem( i18n( "Name" ), 0 );
+ QCStringList l = o->imp()->properties();
+ assert( l.size() == o->imp()->numberOfProperties() );
+ for ( int i = 0; static_cast<uint>( i ) < l.size(); ++i )
+ {
+ QString s = i18n( l[i] );
+ const char* iconfile = o->imp()->iconForProperty( i );
+ int t;
+ if ( iconfile && *iconfile )
+ {
+ QPixmap pix = mdoc.instance()->iconLoader()->loadIcon( iconfile, KIcon::User );
+ t = p->insertItem( QIconSet( pix ), s, i + 1 );
+ }
+ else
+ {
+ t = p->insertItem( s, i + 1 );
+ };
+ assert( t == i + 1 );
+ };
+ int result = p->exec( v->mapToGlobal( d->plc ) );
+ ObjectCalcer::shared_ptr argcalcer;
+ if ( result == -1 ) break;
+ else if ( result == 0 )
+ {
+ argcalcer = o->nameCalcer();
+ if ( !argcalcer )
+ {
+ ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "<unnamed object>" ) ) );
+ o->setNameCalcer( c );
+ argcalcer = c;
+ }
+ }
+ else
+ {
+ assert( static_cast<uint>( result ) < l.size() + 1 );
+ argcalcer = new ObjectPropertyCalcer( o->calcer(), result - 1 );
+ }
+ d->args[d->mwaaws] = argcalcer.get();
+ argcalcer->calc( mdoc.document() );
+
+ updateLinksLabel();
+ updateWiz();
+ break;
+ }
+ default:
+ assert( false );
+ break;
+ };
+}
+
+void TextLabelModeBase::killMode()
+{
+ mdoc.doneMode( this );
+}
+
+void TextLabelModeBase::cancelConstruction()
+{
+ killMode();
+}
+
+void TextLabelModeBase::enableActions()
+{
+ KigMode::enableActions();
+
+ mdoc.aCancelConstruction->setEnabled( true );
+}
+
+void TextLabelModeBase::mouseMoved( QMouseEvent* e, KigWidget* w )
+{
+ if ( d->mwawd == ReallySelectingArgs )
+ {
+ std::vector<ObjectHolder*> os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w );
+ if ( !os.empty() ) w->setCursor( KCursor::handCursor() );
+ else w->setCursor( KCursor::arrowCursor() );
+ }
+ else if ( d->mwawd == SelectingLocation )
+ {
+ std::vector<ObjectHolder*> os = mdoc.document().whatAmIOn( w->fromScreen( e->pos() ), *w );
+ bool attachable = false;
+ d->locationparent = 0;
+ for ( std::vector<ObjectHolder*>::iterator i = os.begin(); i != os.end(); ++i )
+ {
+ if( (*i)->imp()->attachPoint().valid() ||
+ (*i)->imp()->inherits( PointImp::stype() ) ||
+ (*i)->imp()->inherits( CurveImp::stype() ) )
+ {
+ attachable = true;
+ d->locationparent = (*i)->calcer();
+ break;
+ };
+ };
+ w->updateCurPix();
+ if ( attachable )
+ {
+ w->setCursor( KCursor::handCursor() );
+ QString s = d->locationparent->imp()->type()->attachToThisStatement();
+ mdoc.emitStatusBarText( s );
+
+ KigPainter p( w->screenInfo(), &w->curPix, mdoc.document() );
+
+ // set the text next to the arrow cursor
+ QPoint point = e->pos();
+ point.setX(point.x()+15);
+
+ p.drawTextStd( point, s );
+ w->updateWidget( p.overlay() );
+ }
+ else
+ {
+ w->setCursor( KCursor::crossCursor() );
+ mdoc.emitStatusBarText( 0 );
+ w->updateWidget();
+ };
+ }
+}
+
+void TextLabelModeBase::enterTextPageEntered()
+{
+}
+
+void TextLabelModeBase::selectArgumentsPageEntered()
+{
+ updateLinksLabel();
+}
+
+void TextLabelModeBase::cancelPressed()
+{
+ cancelConstruction();
+}
+
+static uint percentCount( const QString& s )
+{
+// QRegExp re( QString::fromUtf8( "%[0-9]" ) );
+ QRegExp re( QString::fromUtf8( "%[\\d]+" ) );
+ int offset = 0;
+ uint percentcount = 0;
+ while ( ( offset = re.search( s, offset ) ) != -1 )
+ {
+ ++percentcount;
+ offset += re.matchedLength();
+ };
+ return percentcount;
+}
+
+void TextLabelModeBase::finishPressed()
+{
+ bool needframe = d->wiz->needFrameCheckBox->isChecked();
+ QString s = d->wiz->labelTextInput->text();
+
+ assert( percentCount( s ) == d->args.size() );
+ if ( d->wiz->currentPage() == d->wiz->enter_text_page )
+ assert( d->args.size() == 0 );
+
+ bool finished = true;
+ for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i )
+ finished &= ( *i != 0 );
+
+ if ( ! finished )
+ KMessageBox::sorry( mdoc.widget(),
+ i18n( "There are '%n' parts in the text that you have not selected a "
+ "value for. Please remove them or select enough arguments." ) );
+ else
+ {
+ finish( d->mcoord, s, d->args, needframe, d->locationparent );
+ killMode();
+ };
+}
+
+void TextLabelModeBase::updateWiz()
+{
+ QString s = d->wiz->labelTextInput->text();
+ uint percentcount = percentCount( s );
+ if ( d->lpc > percentcount )
+ {
+ d->args = argvect( d->args.begin(), d->args.begin() + percentcount );
+ }
+ else if ( d->lpc < percentcount )
+ {
+ d->args.resize( percentcount, 0 );
+ };
+
+ if ( percentcount == 0 && ! s.isEmpty() )
+ {
+ d->wiz->setNextEnabled( d->wiz->enter_text_page, false );
+ d->wiz->setFinishEnabled( d->wiz->enter_text_page, true );
+ d->wiz->setAppropriate( d->wiz->select_arguments_page, false );
+ }
+ else
+ {
+ d->wiz->setAppropriate( d->wiz->select_arguments_page, !s.isEmpty() );
+ d->wiz->setNextEnabled( d->wiz->enter_text_page, ! s.isEmpty() );
+ d->wiz->setFinishEnabled( d->wiz->enter_text_page, false );
+ bool finished = true;
+ for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i )
+ finished &= ( *i != 0 );
+ assert( percentCount( s ) == d->args.size() );
+
+ d->wiz->setFinishEnabled( d->wiz->select_arguments_page, finished );
+ };
+
+ d->lpc = percentcount;
+}
+
+void TextLabelModeBase::labelTextChanged()
+{
+ updateWiz();
+}
+
+void TextLabelModeBase::updateLinksLabel()
+{
+ LinksLabel::LinksLabelEditBuf buf = d->wiz->myCustomWidget1->startEdit();
+ QString s = d->wiz->labelTextInput->text();
+// QRegExp re( "%[0-9]" );
+ QRegExp re( "%[\\d]+" );
+ int prevpos = 0;
+ int pos = 0;
+ uint count = 0;
+ // we split up the string into text and "links"
+ while ( ( pos = re.search( s, pos ) ) != -1 )
+ {
+ // prevpos is the first character after the last match, pos is the
+ // first char of the current match..
+ if ( prevpos != pos )
+ {
+ // there is a text part between the previous and the current
+ // "link"...
+ assert( prevpos < pos );
+ // fetch the text part...
+ QString subs = s.mid( prevpos, pos - prevpos );
+ // and add it...
+ d->wiz->myCustomWidget1->addText( subs, buf );
+ };
+ // we always need a link part...
+ QString linktext( "%1" );
+ assert( count < d->args.size() );
+ if ( d->args[count] )
+ {
+ // if the user has already selected a property, then we show its
+ // value...
+ d->args[count]->imp()->fillInNextEscape( linktext, mdoc.document() );
+ }
+ else
+ // otherwise, we show a stub...
+ linktext = i18n( "argument %1" ).arg( count + 1 );
+
+ d->wiz->myCustomWidget1->addLink( linktext, buf );
+ // set pos and prevpos to the next char after the last match, so
+ // we don't enter infinite loops...
+// pos += 2;
+ pos += re.matchedLength();
+ prevpos = pos;
+ ++count;
+ };
+
+ if ( static_cast<uint>( prevpos ) != s.length() )
+ d->wiz->myCustomWidget1->addText( s.mid( prevpos ), buf );
+
+ d->wiz->myCustomWidget1->applyEdit( buf );
+ d->wiz->relayoutArgsPage();
+
+ d->wiz->resize( d->wiz->size() );
+}
+
+void TextLabelModeBase::linkClicked( int i )
+{
+ mdoc.widget()->setActiveWindow();
+ mdoc.widget()->raise();
+
+ assert( d->args.size() >= static_cast<uint>( i + 1 ) );
+
+ d->mwawd = ReallySelectingArgs;
+ d->mwaaws = i;
+
+ mdoc.emitStatusBarText( i18n( "Selecting argument %1" ).arg( i + 1 ) );
+}
+
+void TextLabelModeBase::redrawScreen( KigWidget* w )
+{
+ w->redrawScreen( std::vector<ObjectHolder*>() );
+ w->updateScrollBars();
+}
+
+void TextLabelModeBase::setCoordinate( const Coordinate& coord )
+{
+ d->mcoord = coord;
+ if ( d->mwawd == SelectingLocation )
+ {
+ d->mwawd = RequestingText;
+ updateWiz();
+ d->wiz->show();
+ // shouldn't be necessary, but seems to be anyway.. :(
+ updateWiz();
+ };
+}
+
+void TextLabelModeBase::setText( const QString& s )
+{
+ d->wiz->labelTextInput->setText( s );
+}
+
+void TextLabelModeBase::setPropertyObjects( const argvect& props )
+{
+ d->args = props;
+ for ( argvect::iterator i = d->args.begin(); i != d->args.end(); ++i )
+ (*i)->calc( mdoc.document() );
+}
+
+TextLabelConstructionMode::TextLabelConstructionMode( KigPart& d )
+ : TextLabelModeBase( d )
+{
+}
+
+TextLabelConstructionMode::~TextLabelConstructionMode()
+{
+}
+
+void TextLabelConstructionMode::finish(
+ const Coordinate& coord, const QString& s,
+ const argvect& props, bool needframe,
+ ObjectCalcer* locationparent )
+{
+ std::vector<ObjectCalcer*> args;
+ for ( argvect::const_iterator i = props.begin();
+ i != props.end(); ++i )
+ args.push_back( i->get() );
+
+ ObjectHolder* label = 0;
+ if ( locationparent )
+ label = ObjectFactory::instance()->attachedLabel( s, locationparent, coord, needframe, args, mdoc.document() );
+ else
+ label = ObjectFactory::instance()->label( s, coord, needframe, args, mdoc.document() );
+ mdoc.addObject( label );
+}
+
+TextLabelRedefineMode::TextLabelRedefineMode( KigPart& d, ObjectTypeCalcer* label )
+ : TextLabelModeBase( d ), mlabel( label )
+{
+ assert( label->imp()->inherits( TextImp::stype() ) );
+ std::vector<ObjectCalcer*> parents = label->parents();
+ assert( parents.size() >= 3 );
+ std::vector<ObjectCalcer*> firstthree( parents.begin(), parents.begin() + 3 );
+ std::vector<ObjectCalcer*> rest( parents.begin() + 3, parents.end() );
+ firstthree = TextType::instance()->argParser().parse( firstthree );
+
+ assert( firstthree[0]->imp()->inherits( IntImp::stype() ) );
+ assert( firstthree[1]->imp()->inherits( PointImp::stype() ) );
+ assert( firstthree[2]->imp()->inherits( StringImp::stype() ) );
+
+ bool frame = static_cast<const IntImp*>( firstthree[0]->imp() )->data() != 0;
+ Coordinate coord = static_cast<const PointImp*>( firstthree[1]->imp() )->coordinate();
+ QString text = static_cast<const StringImp*>( firstthree[2]->imp() )->data();
+
+ // don't set it, let the user redefine it..
+// setCoordinate( coord );
+ setText( text );
+ setFrame( frame );
+
+ argvect v;
+ for ( uint i = 0; i < rest.size(); ++i )
+ {
+ v.push_back( rest[i] );
+ };
+ assert( v.size() == rest.size() );
+
+ setPropertyObjects( v );
+}
+
+TextLabelRedefineMode::~TextLabelRedefineMode()
+{
+}
+
+void TextLabelRedefineMode::finish(
+ const Coordinate& coord, const QString& s,
+ const argvect& props, bool needframe,
+ ObjectCalcer* locationparent )
+{
+ std::vector<ObjectCalcer*> parents = mlabel->parents();
+ assert( parents.size() >= 3 );
+ std::vector<ObjectCalcer*> firstthree( parents.begin(), parents.begin() + 3 );
+ std::vector<ObjectCalcer*> rest( parents.begin() + 3, parents.end() );
+ firstthree = TextType::instance()->argParser().parse( firstthree );
+
+ KigCommand* kc = new KigCommand( mdoc, i18n( "Change Label" ) );
+ MonitorDataObjects mon( firstthree );
+
+ assert( firstthree[0]->imp()->inherits( IntImp::stype() ) );
+ assert( firstthree[1]->imp()->inherits( PointImp::stype() ) );
+ assert( firstthree[2]->imp()->inherits( StringImp::stype() ) );
+
+ assert( dynamic_cast<ObjectConstCalcer*>( firstthree[0] ) );
+ assert( dynamic_cast<ObjectConstCalcer*>( firstthree[2] ) );
+ static_cast<ObjectConstCalcer*>( firstthree[0] )->setImp( new IntImp( needframe ? 1 : 0 ) );
+
+ // we don't do this, because
+ // 1 this isn't necessarily a DataObject, we also support it to be a
+ // user-known point, or an internal constrained point..
+ // 2 we don't know that we don't want it to become a user-known
+ // point or an internal constrained point, instead of a
+ // DataObject..
+ // static_cast<DataObject*>( firstthree[1] )->setImp( new PointImp(
+ // coord ) );
+
+ static_cast<ObjectConstCalcer*>( firstthree[2] )->setImp( new StringImp( s ) );
+ mon.finish( kc );
+
+ std::vector<ObjectCalcer*> oldparents = mlabel->parents();
+ std::vector<ObjectCalcer*> p;
+ for ( argvect::const_iterator i = props.begin();
+ i != props.end(); ++i )
+ p.push_back( i->get() );
+ for ( std::vector<ObjectCalcer*>::iterator i = p.begin();
+ i != p.end(); ++i )
+ ( *i )->calc( mdoc.document() );
+
+ std::vector<ObjectCalcer*> np = firstthree;
+ /*
+ * take advantage of the method "getAttachPoint" that should
+ * do all the work; it is also used when creating a new label
+ */
+ np[1] = ObjectFactory::instance()->getAttachPoint( locationparent, coord, mdoc.document() );
+
+/* this is the old code, just in case... */
+// if ( locationparent && locationparent->imp()->inherits( CurveImp::stype() ) )
+// {
+// double param = static_cast<const CurveImp*>( locationparent->imp() )->getParam( coord, mdoc.document() );
+// np[1] = ObjectFactory::instance()->constrainedPointCalcer( locationparent, param );
+// np[1]->calc( mdoc.document() );
+// }
+// else if ( locationparent )
+// {
+// assert( locationparent->imp()->inherits( PointImp::stype() ) );
+// np[1] = locationparent;
+// }
+// else
+// np[1] = new ObjectConstCalcer( new PointImp( coord ) );
+
+ copy( p.begin(), p.end(), back_inserter( np ) );
+
+ kc->addTask(
+ new ChangeParentsAndTypeTask(
+ mlabel, np, TextType::instance() ) );
+
+ mdoc.history()->addCommand( kc );
+}
+
+void TextLabelModeBase::setFrame( bool f )
+{
+ d->wiz->needFrameCheckBox->setChecked( f );
+}
+
+void TextLabelModeBase::setLocationParent( ObjectCalcer* o )
+{
+ d->locationparent = o;
+}
diff --git a/kig/modes/label.h b/kig/modes/label.h
new file mode 100644
index 00000000..4a3d09f7
--- /dev/null
+++ b/kig/modes/label.h
@@ -0,0 +1,129 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODE_LABEL_H
+#define KIG_MODE_LABEL_H
+
+#include "mode.h"
+
+#include "../objects/object_calcer.h"
+
+#include <vector>
+
+class TextLabelWizard;
+class NormalMode;
+class Coordinate;
+class QString;
+class ObjectPropertyCalcer;
+class ObjectTypeCalcer;
+class ObjectCalcer;
+
+/**
+ * this is the base class for TextLabelConstructionMode and
+ * TextLabelRedefineMode.. most of the work is done in this class,
+ * with some specific things delegated to the children.. Template
+ * method pattern, right ? :)
+ */
+class TextLabelModeBase
+ : public KigMode
+{
+ class Private;
+ Private* d;
+
+public:
+ // below is the interface towards TextLabelWizard...
+ void cancelPressed();
+ void finishPressed();
+ void enterTextPageEntered();
+ void selectArgumentsPageEntered();
+ void labelTextChanged();
+ void linkClicked( int );
+ void redrawScreen( KigWidget* w );
+
+protected:
+ typedef std::vector<ObjectCalcer::shared_ptr> argvect;
+ // the protected interface for subclasses
+ TextLabelModeBase( KigPart& d );
+ ~TextLabelModeBase();
+
+ void setCoordinate( const Coordinate& coord );
+ void setText( const QString& s );
+ void setLocationParent( ObjectCalcer* o );
+ /**
+ * objects you pass here, should be newly created property objects,
+ * that have no children..
+ */
+ void setPropertyObjects( const argvect& props );
+ void setFrame( bool f );
+
+ virtual void finish( const Coordinate& c, const QString& s,
+ const argvect& props, bool needframe,
+ ObjectCalcer* locationparent ) = 0;
+
+private:
+ // the KigMode interface..
+ void leftClicked( QMouseEvent*, KigWidget* );
+ void leftReleased( QMouseEvent*, KigWidget* );
+
+ void mouseMoved( QMouseEvent*, KigWidget* );
+
+ void enableActions();
+
+ void cancelConstruction();
+
+ void killMode();
+
+private:
+ /**
+ * \internal
+ * What Are We Doing...
+ * the diff between SelectingArgs and ReallySelectingArgs is that
+ * the latter means the user is selecting an arg in the kig window,
+ * whereas the first only means that he's looking at the second
+ * page of the wizard...
+ */
+ typedef enum { SelectingLocation, RequestingText, SelectingArgs, ReallySelectingArgs } wawdtype;
+
+ void updateWiz();
+ void updateLinksLabel();
+};
+
+class TextLabelConstructionMode
+ : public TextLabelModeBase
+{
+public:
+ TextLabelConstructionMode( KigPart& d );
+ ~TextLabelConstructionMode();
+
+ void finish( const Coordinate& coord, const QString& s,
+ const argvect& props, bool needframe,
+ ObjectCalcer* locationparent );
+};
+
+class TextLabelRedefineMode
+ : public TextLabelModeBase
+{
+ ObjectTypeCalcer* mlabel;
+ void finish( const Coordinate& coord, const QString& s,
+ const argvect& props, bool needframe,
+ ObjectCalcer* locationparent );
+public:
+ TextLabelRedefineMode( KigPart& d, ObjectTypeCalcer* label );
+ ~TextLabelRedefineMode();
+};
+
+#endif
diff --git a/kig/modes/linkslabel.cpp b/kig/modes/linkslabel.cpp
new file mode 100644
index 00000000..572c0bf8
--- /dev/null
+++ b/kig/modes/linkslabel.cpp
@@ -0,0 +1,134 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library 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
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301 USA
+
+
+#include "linkslabel.h"
+#include "linkslabel.moc"
+
+#include <qlabel.h>
+#include <kurllabel.h>
+#include <qlayout.h>
+
+#include <vector>
+#include <algorithm>
+#include <functional>
+
+#include <assert.h>
+using namespace std;
+
+class LinksLabel::Private
+{
+public:
+ QHBoxLayout* layout;
+ std::vector<QLabel*> labels;
+ std::vector<KURLLabel*> urllabels;
+};
+
+LinksLabel::LinksLabel( QWidget* parent, const char* name )
+ : QWidget( parent, name )
+{
+ p = new Private;
+ p->layout = new QHBoxLayout( this );
+
+ QLabel* l = new QLabel( QString::fromUtf8( "Dit is een " ), this );
+ p->labels.push_back( l );
+ p->layout->addWidget( l );
+
+ KURLLabel* u = new KURLLabel( QString::fromUtf8( "http://www.kde.org/" ),
+ QString::fromUtf8( "url"), this );
+ p->urllabels.push_back( u );
+ p->layout->addWidget( u );
+
+ l = new QLabel( QString::fromUtf8( " !" ), this );
+ p->labels.push_back( l );
+ p->layout->addWidget(l );
+
+ p->layout->activate();
+}
+
+LinksLabel::~LinksLabel()
+{
+ delete p;
+}
+
+void LinksLabel::urlClicked()
+{
+ const QObject* o = sender();
+ std::vector<KURLLabel*>::iterator i = std::find( p->urllabels.begin(), p->urllabels.end(), static_cast<const KURLLabel*>( o ) );
+ assert( i != p->urllabels.end() );
+ emit linkClicked( i - p->urllabels.begin() );
+}
+
+LinksLabel::LinksLabelEditBuf LinksLabel::startEdit()
+{
+ return LinksLabelEditBuf();
+}
+
+void LinksLabel::addText( const QString& s, LinksLabelEditBuf& buf )
+{
+ buf.data.push_back( std::pair<bool, QString>( false, s ) );
+}
+
+void LinksLabel::addLink( const QString& s, LinksLabelEditBuf& buf )
+{
+ buf.data.push_back( std::pair<bool, QString>( true, s ) );
+}
+
+namespace {
+ void deleteObj( QObject* o ) { delete o; }
+}
+
+void LinksLabel::applyEdit( LinksLabelEditBuf& buf )
+{
+ std::for_each( p->urllabels.begin(), p->urllabels.end(), deleteObj );
+ std::for_each( p->labels.begin(), p->labels.end(), deleteObj );
+ p->urllabels.clear();
+ p->labels.clear();
+
+ delete p->layout;
+ p->layout = new QHBoxLayout( this );
+
+ for ( LinksLabelEditBuf::vec::iterator i = buf.data.begin(); i != buf.data.end(); ++i )
+ {
+ if ( i->first )
+ {
+ // we need a KURLLabel...
+ // the url is an unused stub...
+ KURLLabel* l = new KURLLabel( QString::fromUtf8( "http://edu.kde.org/kig" ),
+ i->second, this );
+ p->urllabels.push_back( l );
+ p->layout->addWidget( l );
+ connect( l, SIGNAL( leftClickedURL() ), SLOT( urlClicked() ) );
+ }
+ else
+ {
+ // we need a normal label...
+ QLabel* l = new QLabel( i->second, this );
+ p->labels.push_back( l );
+ p->layout->addWidget( l );
+ };
+ };
+
+ QSpacerItem* spacer = new QSpacerItem( 40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+
+ p->layout->addItem( spacer );
+
+ p->layout->activate();
+
+ std::for_each( p->urllabels.begin(), p->urllabels.end(), mem_fun( &QWidget::show ) );
+ std::for_each( p->labels.begin(), p->labels.end(), mem_fun( &QWidget::show ) );
+}
diff --git a/kig/modes/linkslabel.h b/kig/modes/linkslabel.h
new file mode 100644
index 00000000..ba64dbc2
--- /dev/null
+++ b/kig/modes/linkslabel.h
@@ -0,0 +1,85 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+
+// This library 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
+// Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+// 02110-1301 USA
+
+#ifndef KIG_lINKS_LABEL_H
+#define KIG_lINKS_LABEL_H
+
+#include <qwidget.h>
+
+#include <vector>
+#include <utility>
+
+/**
+ * this widget shows a line of text, with some links underlined, and
+ * emits a signal if one of the links is clicked...
+ */
+class LinksLabel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ LinksLabel( QWidget* parent = 0, const char* name = 0 );
+ ~LinksLabel();
+
+ class LinksLabelEditBuf
+ {
+ public:
+ friend class LinksLabel;
+ ~LinksLabelEditBuf() {}
+ private:
+ // declare these private so only LinksLabel can use them...
+ LinksLabelEditBuf() {}
+ typedef std::vector<std::pair<bool,QString> > vec;
+ vec data;
+ };
+
+ /**
+ * start editing, start recording changes in a LinksLabelEditBuf,
+ * but don't apply them until after endEdit();
+ */
+ LinksLabelEditBuf startEdit();
+ /**
+ * add a piece of normal text..
+ */
+ void addText( const QString& s, LinksLabelEditBuf& buf );
+ /**
+ * add a link...
+ */
+ void addLink( const QString& s, LinksLabelEditBuf& buf );
+ /**
+ * apply the changes... This clears the current contents and adds
+ * the new data...
+ */
+ void applyEdit( LinksLabelEditBuf& buf );
+
+signals:
+ /**
+ * the user clicked on a link. The index is the order in which it
+ * was added. E.g. this signal is emitted with arg 0 if the link
+ * you first added is clicked, argument 2 for the third link etc.
+ */
+ void linkClicked( int i );
+
+private slots:
+ void urlClicked();
+
+private:
+ class Private;
+ Private* p;
+};
+
+#endif // KDE_URLS_LABEL_H
diff --git a/kig/modes/macro.cc b/kig/modes/macro.cc
new file mode 100644
index 00000000..879466dc
--- /dev/null
+++ b/kig/modes/macro.cc
@@ -0,0 +1,245 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "macro.h"
+
+#include "macrowizard.h"
+#include "dragrectmode.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../misc/kigpainter.h"
+#include "../misc/object_constructor.h"
+#include "../misc/lists.h"
+#include "../misc/guiaction.h"
+#include "../objects/object_imp.h"
+
+#include <klineedit.h>
+#include <kmessagebox.h>
+#include <kcursor.h>
+#include <klocale.h>
+
+#include <functional>
+#include <algorithm>
+
+using namespace std;
+
+DefineMacroMode::DefineMacroMode( KigPart& d )
+ : BaseMode( d )
+{
+ mwizard = new MacroWizard( d.widget(), this );
+ mwizard->show();
+ updateNexts();
+}
+
+DefineMacroMode::~DefineMacroMode()
+{
+ delete mwizard;
+}
+
+void DefineMacroMode::abandonMacro()
+{
+ mdoc.doneMode( this );
+}
+
+void DefineMacroMode::updateNexts()
+{
+ mwizard->setNextEnabled( mwizard->mpgiven,
+ !mgiven.empty() );
+ mwizard->setNextEnabled( mwizard->mpfinal,
+ !mfinal.empty() );
+ mwizard->setFinishEnabled(
+ mwizard->mpname,
+ !mwizard->KLineEdit2->text().isEmpty()
+ );
+}
+
+void DefineMacroMode::enableActions()
+{
+ KigMode::enableActions();
+ // we don't enable any actions...
+}
+
+void DefineMacroMode::givenPageEntered()
+{
+ std::vector<ObjectHolder*> given( mgiven.begin(), mgiven.end() );
+ static_cast<KigView*>( mdoc.widget() )->realWidget()->redrawScreen( given );
+ updateNexts();
+}
+
+void DefineMacroMode::finalPageEntered()
+{
+ std::vector<ObjectHolder*> final( mfinal.begin(), mfinal.end() );
+ static_cast<KigView*>( mdoc.widget() )->realWidget()->redrawScreen( final );
+
+ updateNexts();
+}
+
+void DefineMacroMode::namePageEntered()
+{
+ ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer;
+ std::vector<ObjectCalcer*> given;
+ std::transform( mgiven.begin(), mgiven.end(),
+ std::back_inserter( given ),
+ std::mem_fun( memfun ) );
+ std::vector<ObjectCalcer*> final;
+ std::transform( mfinal.begin(), mfinal.end(),
+ std::back_inserter( final ),
+ std::mem_fun( memfun ) );
+ ObjectHierarchy hier( given, final );
+ if ( hier.resultDoesNotDependOnGiven() )
+ {
+ KMessageBox::sorry( mwizard,
+ i18n( "One of the result objects you selected "
+ "cannot be calculated from the given objects. "
+ "Kig cannot calculate this macro because of this. "
+ "Please press Back, and construct the objects "
+ "in the correct order..." ) );
+ mwizard->back();
+ }
+ else if( !hier.allGivenObjectsUsed() )
+ {
+ KMessageBox::sorry( mwizard,
+ i18n( "One of the given objects is not used in the "
+ "calculation of the resultant objects. This "
+ "probably means you are expecting Kig to do "
+ "something impossible. Please check the "
+ "macro and try again." ) );
+ mwizard->back();
+ }
+
+ static_cast<KigView*>( mdoc.widget() )->realWidget()->redrawScreen( std::vector<ObjectHolder*>() );
+
+ updateNexts();
+}
+
+void DefineMacroMode::finishPressed()
+{
+ ObjectCalcer* (ObjectHolder::*memfun)() = &ObjectHolder::calcer;
+ std::vector<ObjectCalcer*> given;
+ std::transform( mgiven.begin(), mgiven.end(),
+ std::back_inserter( given ),
+ std::mem_fun( memfun ) );
+ std::vector<ObjectCalcer*> final;
+ std::transform( mfinal.begin(), mfinal.end(),
+ std::back_inserter( final ),
+ std::mem_fun( memfun ) );
+ ObjectHierarchy hier( given, final );
+ MacroConstructor* ctor =
+ new MacroConstructor( hier,
+ mwizard->KLineEdit2->text(),
+ mwizard->KLineEdit1->text() );
+ ConstructibleAction* act = new ConstructibleAction( ctor, 0 );
+ MacroList::instance()->add( new Macro( act, ctor ) );
+
+ abandonMacro();
+}
+
+void DefineMacroMode::cancelPressed()
+{
+ abandonMacro();
+}
+
+void DefineMacroMode::macroNameChanged()
+{
+ mwizard->setFinishEnabled(
+ mwizard->mpname,
+ !mwizard->KLineEdit2->text().isEmpty()
+ );
+}
+
+void DefineMacroMode::dragRect( const QPoint& p, KigWidget& w )
+{
+ if ( mwizard->currentPage() == mwizard->mpname ) return;
+ std::vector<ObjectHolder*>* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal;
+ DragRectMode dm( p, mdoc, w );
+ mdoc.runMode( &dm );
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+ if ( ! dm.cancelled() )
+ {
+ std::vector<ObjectHolder*> ret = dm.ret();
+ if ( dm.needClear() )
+ {
+ pter.drawObjects( objs->begin(), objs->end(), false );
+ objs->clear();
+ }
+
+ std::copy( ret.begin(), ret.end(), std::back_inserter( *objs ) );
+ pter.drawObjects( objs->begin(), objs->end(), true );
+ };
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+
+ updateNexts();
+}
+
+void DefineMacroMode::leftClickedObject( ObjectHolder* o, const QPoint&,
+ KigWidget& w, bool )
+{
+ if ( mwizard->currentPage() == mwizard->mpname ) return;
+ std::vector<ObjectHolder*>* objs = mwizard->currentPage() == mwizard->mpgiven ? &mgiven : &mfinal;
+ std::vector<ObjectHolder*>::iterator iter = std::find( objs->begin(), objs->end(), o );
+ bool isselected = ( iter != objs->end() );
+ if ( isselected ) objs->erase( iter );
+ else objs->push_back( o );
+
+ KigPainter p( w.screenInfo(), &w.stillPix, mdoc.document() );
+ p.drawObject( o, !isselected );
+ w.updateCurPix( p.overlay() );
+ w.updateWidget();
+
+ updateNexts();
+}
+
+void DefineMacroMode::mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& pt, KigWidget& w, bool )
+{
+ w.updateCurPix();
+
+ if ( os.empty() )
+ {
+ w.setCursor( KCursor::arrowCursor() );
+ mdoc.emitStatusBarText( 0 );
+ w.updateWidget();
+ }
+ else
+ {
+ // the cursor is over an object, show object type next to cursor
+ // and set statusbar text
+
+ w.setCursor( KCursor::handCursor() );
+ QString selectstat = os.front()->selectStatement();
+
+ // statusbar text
+ mdoc.emitStatusBarText( selectstat );
+ KigPainter p( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ // set the text next to the arrow cursor
+ QPoint point = pt;
+ point.setX(point.x()+15);
+
+ p.drawTextStd( point, selectstat );
+ w.updateWidget( p.overlay() );
+ }
+}
+
+void DefineMacroMode::rightClicked( const std::vector<ObjectHolder*>&, const QPoint&, KigWidget& )
+{
+}
+
+void DefineMacroMode::midClicked( const QPoint&, KigWidget& )
+{
+}
+
diff --git a/kig/modes/macro.h b/kig/modes/macro.h
new file mode 100644
index 00000000..4bf8c43e
--- /dev/null
+++ b/kig/modes/macro.h
@@ -0,0 +1,68 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODES_MACRO_H
+#define KIG_MODES_MACRO_H
+
+#include "base_mode.h"
+
+#include <qobject.h>
+
+class MacroWizard;
+
+class DefineMacroMode
+ : public BaseMode
+{
+public:
+ DefineMacroMode( KigPart& );
+ ~DefineMacroMode();
+
+ void dragRect( const QPoint& p, KigWidget& w );
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void rightClicked( const std::vector<ObjectHolder*>& oco, const QPoint& p, KigWidget& w );
+ void midClicked( const QPoint& p, KigWidget& w );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w, bool shiftpressed );
+
+ // called by MacroWizard class
+ void givenPageEntered();
+ void finalPageEntered();
+ void namePageEntered();
+ void finishPressed();
+ void cancelPressed();
+ void macroNameChanged();
+
+protected:
+ void enableActions();
+ /**
+ * update the enabled state of the next buttons on the wizard...
+ */
+ void updateNexts();
+ /**
+ * quit this mode...
+ */
+ void abandonMacro();
+
+ QPoint plc;
+ MacroWizard* mwizard;
+
+ // we can't use a set for this because the order is important
+ std::vector<ObjectHolder*> mgiven;
+ std::vector<ObjectHolder*> mfinal;
+};
+
+#endif
diff --git a/kig/modes/macrowizard.cc b/kig/modes/macrowizard.cc
new file mode 100644
index 00000000..e6315caf
--- /dev/null
+++ b/kig/modes/macrowizard.cc
@@ -0,0 +1,90 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "macrowizard.h"
+#include "macrowizard.moc"
+
+#include "macro.h"
+
+#include <kdebug.h>
+#include <klineedit.h>
+#include <kapplication.h>
+
+MacroWizard::MacroWizard( QWidget* parent, DefineMacroMode* m )
+ : MacroWizardBase( parent, "Define Macro Wizard", false ), mmode( m )
+{
+ connect( KLineEdit2, SIGNAL( textChanged( const QString& ) ),
+ this, SLOT( nameTextChanged( const QString& ) ) );
+ connect( this, SIGNAL( helpClicked() ), this,
+ SLOT( slotHelpClicked() ) );
+}
+
+MacroWizard::~MacroWizard()
+{
+}
+
+void MacroWizard::back()
+{
+ if ( currentPage() == mpfinal )
+ {
+ // currentPage() is not yet updated when we get here, so this
+ // means that the page about to be shown is actually mpgiven...
+ mmode->givenPageEntered();
+ }
+ else if ( currentPage() == mpname )
+ {
+ mmode->finalPageEntered();
+ }
+ MacroWizardBase::back();
+}
+
+void MacroWizard::next()
+{
+ if ( currentPage() == mpgiven )
+ {
+ // currentPage() is not yet updated when we get here, so this
+ // means that the page about to be shown is actually mpfinal...
+ mmode->finalPageEntered();
+ }
+ else if ( currentPage() == mpfinal )
+ {
+ mmode->namePageEntered();
+ }
+ MacroWizardBase::next();
+}
+
+void MacroWizard::reject()
+{
+ MacroWizardBase::reject();
+ mmode->cancelPressed();
+}
+
+void MacroWizard::nameTextChanged( const QString& )
+{
+ mmode->macroNameChanged();
+}
+
+void MacroWizard::accept()
+{
+ mmode->finishPressed();
+}
+
+void MacroWizard::slotHelpClicked()
+{
+ kapp->invokeHelp( QString::fromLatin1( "defining-macros"),
+ QString::fromLatin1( "kig" ) );
+}
diff --git a/kig/modes/macrowizard.h b/kig/modes/macrowizard.h
new file mode 100644
index 00000000..dfce8b06
--- /dev/null
+++ b/kig/modes/macrowizard.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef MACROWIZARD_H
+#define MACROWIZARD_H
+
+#include "macrowizardbase.h"
+
+class DefineMacroMode;
+
+class MacroWizard : public MacroWizardBase
+{
+ Q_OBJECT
+public:
+ MacroWizard( QWidget* parent, DefineMacroMode* m );
+ ~MacroWizard();
+
+ void back();
+ void next();
+ void reject();
+ void accept();
+private slots:
+ void nameTextChanged( const QString& );
+ void slotHelpClicked();
+private:
+ DefineMacroMode* mmode;
+};
+
+#endif // MACROWIZARD_H
diff --git a/kig/modes/macrowizardbase.ui b/kig/modes/macrowizardbase.ui
new file mode 100644
index 00000000..d3929ad8
--- /dev/null
+++ b/kig/modes/macrowizardbase.ui
@@ -0,0 +1,188 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>MacroWizardBase</class>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>MacroWizardBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>4</x>
+ <y>0</y>
+ <width>344</width>
+ <height>172</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>0</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>Define New Macro</string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mpgiven</cstring>
+ </property>
+ <attribute name="title">
+ <string>Given Objects</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Select the "given" objects for your new macro and press "Next".</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mpfinal</cstring>
+ </property>
+ <attribute name="title">
+ <string>Final Object</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Select the final object(s) for your new macro.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>mpname</cstring>
+ </property>
+ <attribute name="title">
+ <string>Name</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Enter a name and description for your new type.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>KLineEdit2</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>KLineEdit2</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2_2</cstring>
+ </property>
+ <property name="text">
+ <string>Description:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>KLineEdit1</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>KLineEdit1</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klineedit.h</includehint>
+ <includehint>klineedit.h</includehint>
+</includehints>
+</UI>
diff --git a/kig/modes/mode.cc b/kig/modes/mode.cc
new file mode 100644
index 00000000..9d95b64d
--- /dev/null
+++ b/kig/modes/mode.cc
@@ -0,0 +1,133 @@
+/**
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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 "mode.h"
+
+#include "../kig/kig_part.h"
+
+#include <kaction.h>
+
+void KigMode::enableActions()
+{
+ mdoc.enableConstructActions( false );
+ mdoc.aSelectAll->setEnabled( false );
+ mdoc.aDeselectAll->setEnabled( false );
+ mdoc.aInvertSelection->setEnabled( false );
+ mdoc.aCancelConstruction->setEnabled( false );
+ mdoc.aConfigureTypes->setEnabled( false );
+ mdoc.aDeleteObjects->setEnabled( false );
+ mdoc.aShowHidden->setEnabled( false );
+ mdoc.aNewMacro->setEnabled( false );
+ mdoc.action( "edit_undo" )->setEnabled( false );
+ mdoc.action( "edit_redo" )->setEnabled( false );
+}
+
+KigMode::~KigMode()
+{
+}
+
+KigMode::KigMode( KigPart& d )
+ : mdoc( d )
+{
+}
+
+void KigMode::leftClicked( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::leftMouseMoved( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::leftReleased( QMouseEvent*, KigWidget* )
+{
+ /* insist disabling the undo button to avoid crashes */
+ mdoc.action( "edit_undo" )->setEnabled( false );
+ mdoc.action( "edit_redo" )->setEnabled( false );
+}
+
+void KigMode::midClicked( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::midMouseMoved( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::midReleased( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::rightClicked( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::rightMouseMoved( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::rightReleased( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::mouseMoved( QMouseEvent*, KigWidget* )
+{
+}
+
+void KigMode::cancelConstruction()
+{
+}
+
+void KigMode::deleteObjects()
+{
+}
+
+void KigMode::showHidden()
+{
+}
+
+void KigMode::newMacro()
+{
+}
+
+void KigMode::editTypes()
+{
+}
+
+void KigMode::redrawScreen( KigWidget* )
+{
+}
+
+StdConstructionMode* KigMode::toStdConstructionMode()
+{
+ return 0;
+}
+
+void KigMode::selectAll()
+{
+}
+
+void KigMode::deselectAll()
+{
+}
+
+void KigMode::invertSelection()
+{
+}
diff --git a/kig/modes/mode.h b/kig/modes/mode.h
new file mode 100644
index 00000000..6f476072
--- /dev/null
+++ b/kig/modes/mode.h
@@ -0,0 +1,91 @@
+/*
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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
+*/
+
+#ifndef KIG_PART_MODE_H
+#define KIG_PART_MODE_H
+
+#include <qnamespace.h>
+
+class KigDocument;
+class KigPart;
+class KigWidget;
+class QMouseEvent;
+class StdConstructionMode;
+
+/**
+ * this is an ABC of a class containing the current "Mode" of the Kig
+ * document... It tells us how to respond to a certain event.
+ */
+class KigMode
+ : public Qt
+{
+public:
+ virtual ~KigMode();
+
+ virtual StdConstructionMode* toStdConstructionMode();
+
+ virtual void leftClicked( QMouseEvent*, KigWidget* );
+ /**
+ * this means: mouse moved with left mouse button down (in case that
+ * wasn't clear...)
+ */
+ virtual void leftMouseMoved( QMouseEvent*, KigWidget* );
+ virtual void leftReleased( QMouseEvent*, KigWidget* );
+ virtual void midClicked( QMouseEvent*, KigWidget* );
+ virtual void midMouseMoved( QMouseEvent*, KigWidget* );
+ virtual void midReleased( QMouseEvent*, KigWidget* );
+ virtual void rightClicked( QMouseEvent*, KigWidget* );
+ virtual void rightMouseMoved( QMouseEvent*, KigWidget* );
+ virtual void rightReleased( QMouseEvent*, KigWidget* );
+ /**
+ * mouse moved without any buttons down...
+ */
+ virtual void mouseMoved( QMouseEvent*, KigWidget* );
+
+ /**
+ * actions: we enable the actions we want when our mode is made
+ * active. These actions are members of KigDocument, and call slots
+ * on KigDocument. These slots all call the correspondent mode()
+ * member. Modes reimplement the ones they need, and turn on the
+ * actions they support in enableActions().
+ */
+ virtual void enableActions();
+
+ virtual void cancelConstruction();
+ virtual void deleteObjects();
+ virtual void showHidden();
+ virtual void newMacro();
+ virtual void editTypes();
+ virtual void selectAll();
+ virtual void deselectAll();
+ virtual void invertSelection();
+
+ /**
+ * Redraw the document on KigWidget \p w . It's up to the mode to
+ * refresh the screen...
+ */
+ virtual void redrawScreen( KigWidget* w );
+protected:
+ KigPart& mdoc;
+
+ KigMode( KigPart& d );
+};
+
+#endif
diff --git a/kig/modes/moving.cc b/kig/modes/moving.cc
new file mode 100644
index 00000000..e628a7ce
--- /dev/null
+++ b/kig/modes/moving.cc
@@ -0,0 +1,245 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "moving.h"
+
+#include "normal.h"
+
+#include "../objects/object_imp.h"
+#include "../objects/object_factory.h"
+#include "../kig/kig_document.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_view.h"
+#include "../kig/kig_commands.h"
+#include "../misc/kigpainter.h"
+#include "../misc/calcpaths.h"
+#include "../misc/coordinate_system.h"
+
+#include <qevent.h>
+
+#include <functional>
+#include <algorithm>
+#include <map>
+
+void MovingModeBase::initScreen( const std::vector<ObjectCalcer*>& in )
+{
+ mcalcable = in;
+ std::set<ObjectCalcer*> calcableset( mcalcable.begin(), mcalcable.end() );
+
+ // don't try to move objects that have been deleted from the
+ // document or internal objects that the user is not aware of..
+ std::vector<ObjectHolder*> docobjs = mdoc.document().objects();
+ for ( std::vector<ObjectHolder*>::iterator i = docobjs.begin();
+ i != docobjs.end(); ++i )
+ if ( calcableset.find( ( *i )->calcer() ) != calcableset.end() )
+ mdrawable.push_back( *i );
+
+ std::set<ObjectHolder*> docobjsset( docobjs.begin(), docobjs.end() );
+ std::set<ObjectHolder*> drawableset( mdrawable.begin(), mdrawable.end() );
+ std::set<ObjectHolder*> notmovingobjs;
+ std::set_difference( docobjsset.begin(), docobjsset.end(), drawableset.begin(), drawableset.end(),
+ std::inserter( notmovingobjs, notmovingobjs.begin() ) );
+
+ mview.clearStillPix();
+ KigPainter p( mview.screenInfo(), &mview.stillPix, mdoc.document() );
+ p.drawGrid( mdoc.document().coordinateSystem(), mdoc.document().grid(),
+ mdoc.document().axes() );
+ p.drawObjects( notmovingobjs.begin(), notmovingobjs.end(), false );
+ mview.updateCurPix();
+
+ KigPainter p2( mview.screenInfo(), &mview.curPix, mdoc.document() );
+ p2.drawObjects( drawableset.begin(), drawableset.end(), true );
+}
+
+void MovingModeBase::leftReleased( QMouseEvent*, KigWidget* v )
+{
+ // clean up after ourselves:
+ for ( std::vector<ObjectCalcer*>::iterator i = mcalcable.begin();
+ i != mcalcable.end(); ++i )
+ ( *i )->calc( mdoc.document() );
+ stopMove();
+ mdoc.setModified( true );
+
+ // refresh the screen:
+ v->redrawScreen( std::vector<ObjectHolder*>() );
+ v->updateScrollBars();
+
+ mdoc.doneMode( this );
+}
+
+void MovingModeBase::mouseMoved( QMouseEvent* e, KigWidget* v )
+{
+ v->updateCurPix();
+ Coordinate c = v->fromScreen( e->pos() );
+
+ bool snaptogrid = e->state() & Qt::ShiftButton;
+ moveTo( c, snaptogrid );
+ for ( std::vector<ObjectCalcer*>::iterator i = mcalcable.begin();
+ i != mcalcable.end(); ++i )
+ ( *i )->calc( mdoc.document() );
+ KigPainter p( v->screenInfo(), &v->curPix, mdoc.document() );
+ // TODO: only draw the explicitly moving objects as selected, the
+ // other ones as deselected.. Needs some support from the
+ // subclasses..
+ p.drawObjects( mdrawable, true );
+ v->updateWidget( p.overlay() );
+ v->updateScrollBars();
+}
+
+class MovingMode::Private
+{
+public:
+ // explicitly moving objects: these are the objects that the user
+ // requested to move...
+ std::vector<ObjectCalcer*> emo;
+ // point where we started moving..
+ Coordinate pwwsm;
+ MonitorDataObjects* mon;
+ // we keep a map from the emo objects to their reference location.
+ // This is the location that they claim to be at before moving
+ // starts, and we use it as a reference point to determine where
+ // they should move next..
+ std::map<const ObjectCalcer*, Coordinate> refmap;
+};
+
+MovingMode::MovingMode( const std::vector<ObjectHolder*>& os, const Coordinate& c,
+ KigWidget& v, KigPart& doc )
+ : MovingModeBase( doc, v ), d( new Private )
+{
+ d->pwwsm = c;
+ std::vector<ObjectCalcer*> emo;
+ std::set<ObjectCalcer*> objs;
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ if ( (*i)->canMove() )
+ {
+ emo.push_back( ( *i )->calcer() );
+ d->refmap[( *i )->calcer()] = (*i)->moveReferencePoint();
+ objs.insert( ( *i )->calcer() );
+ std::vector<ObjectCalcer*> parents = ( *i )->calcer()->movableParents();
+ objs.insert( parents.begin(), parents.end() );
+ };
+
+ emo = calcPath( emo );
+ for ( std::vector<ObjectCalcer*>::const_iterator i = emo.begin(); i != emo.end(); ++i )
+ if ( !isChild( *i, d->emo ) )
+ d->emo.push_back( *i );
+
+ d->mon = new MonitorDataObjects( std::vector<ObjectCalcer*>( objs.begin(),objs.end() ) );
+
+ std::set<ObjectCalcer*> tmp = objs;
+ for ( std::set<ObjectCalcer*>::const_iterator i = tmp.begin(); i != tmp.end(); ++i )
+ {
+ std::set<ObjectCalcer*> children = getAllChildren(*i);
+ objs.insert( children.begin(), children.end() );
+ }
+
+ initScreen( calcPath( std::vector<ObjectCalcer*>( objs.begin(), objs.end() ) ) );
+}
+
+void MovingMode::stopMove()
+{
+ QString text = d->emo.size() == 1 ?
+ d->emo[0]->imp()->type()->moveAStatement() :
+ i18n( "Move %1 Objects" ).arg( d->emo.size() );
+ KigCommand* mc = new KigCommand( mdoc, text );
+ d->mon->finish( mc );
+ mdoc.history()->addCommand( mc );
+}
+
+void MovingMode::moveTo( const Coordinate& o, bool snaptogrid )
+{
+ for( std::vector<ObjectCalcer*>::iterator i = d->emo.begin(); i != d->emo.end(); ++i )
+ {
+ assert( d->refmap.find( *i ) != d->refmap.end() );
+ Coordinate nc = d->refmap[*i] + ( o - d->pwwsm );
+ if ( snaptogrid ) nc = mdoc.document().coordinateSystem().snapToGrid( nc, mview );
+ (*i)->move( nc, mdoc.document() );
+ };
+}
+
+PointRedefineMode::PointRedefineMode( ObjectHolder* p, KigPart& d, KigWidget& v )
+ : MovingModeBase( d, v ), mp( p ), mmon( 0 )
+{
+ assert( dynamic_cast<ObjectTypeCalcer*>( p->calcer() ) );
+ moldtype = static_cast<ObjectTypeCalcer*>( p->calcer() )->type();
+ std::vector<ObjectCalcer*> oldparents = p->calcer()->parents();
+ std::copy( oldparents.begin(), oldparents.end(), std::back_inserter( moldparents ) );
+
+ std::vector<ObjectCalcer*> parents = getAllParents( mp->calcer() );
+ mmon = new MonitorDataObjects( parents );
+ std::vector<ObjectCalcer*> moving = parents;
+ std::set<ObjectCalcer*> children = getAllChildren( mp->calcer() );
+ std::copy( children.begin(), children.end(), std::back_inserter( moving ) );
+ initScreen( moving );
+}
+
+void PointRedefineMode::moveTo( const Coordinate& o, bool snaptogrid )
+{
+ Coordinate realo =
+ snaptogrid ? mdoc.document().coordinateSystem().snapToGrid( o, mview ) : o;
+ ObjectFactory::instance()->redefinePoint(
+ static_cast<ObjectTypeCalcer*>( mp->calcer() ), realo, mdoc.document(), mview );
+}
+
+PointRedefineMode::~PointRedefineMode()
+{
+}
+
+MovingModeBase::MovingModeBase( KigPart& doc, KigWidget& v )
+ : KigMode( doc ), mview( v )
+{
+}
+
+MovingModeBase::~MovingModeBase()
+{
+}
+
+void MovingModeBase::leftMouseMoved( QMouseEvent* e, KigWidget* v )
+{
+ mouseMoved( e, v );
+}
+
+MovingMode::~MovingMode()
+{
+ delete d->mon;
+ delete d;
+}
+
+void PointRedefineMode::stopMove()
+{
+ assert( dynamic_cast<ObjectTypeCalcer*>( mp->calcer() ) );
+ ObjectTypeCalcer* mpcalc = static_cast<ObjectTypeCalcer*>( mp->calcer() );
+
+ std::vector<ObjectCalcer*> newparents = mpcalc->parents();
+ std::vector<ObjectCalcer::shared_ptr> newparentsref(
+ newparents.begin(), newparents.end() );
+ const ObjectType* newtype = mpcalc->type();
+
+ std::vector<ObjectCalcer*> oldparents;
+ for( std::vector<ObjectCalcer::shared_ptr>::iterator i = moldparents.begin();
+ i != moldparents.end(); ++i )
+ oldparents.push_back( i->get() );
+ mpcalc->setType( moldtype );
+ mpcalc->setParents( oldparents );
+ mp->calc( mdoc.document() );
+
+ KigCommand* command = new KigCommand( mdoc, i18n( "Redefine Point" ) );
+ command->addTask(
+ new ChangeParentsAndTypeTask( mpcalc, newparents, newtype ) );
+ mmon->finish( command );
+ mdoc.history()->addCommand( command );
+}
diff --git a/kig/modes/moving.h b/kig/modes/moving.h
new file mode 100644
index 00000000..32828db3
--- /dev/null
+++ b/kig/modes/moving.h
@@ -0,0 +1,101 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef MOVING_H
+#define MOVING_H
+
+#include "mode.h"
+
+#include "../misc/coordinate.h"
+#include "../objects/object_calcer.h"
+
+class ObjectType;
+class Coordinate;
+class NormalPoint;
+class KigWidget;
+class KigDocument;
+class MonitorDataObjects;
+
+/**
+ * "Template method" pattern ( see the Design patterns book ):
+ * This is a base class for two modes: normal MovingMode: used for
+ * moving a set of objects around, using Object::startMove,
+ * Object::moveTo and Object::stopMove, and another mode
+ * PointRedefineMode, used for redefining a NormalPoint...
+ */
+class MovingModeBase
+ : public KigMode
+{
+protected:
+ KigWidget& mview;
+private:
+ // all moving objects: these objects are all of the objects that
+ // need to be redrawn every time the cursor moves, and after calc is
+ // called.
+ std::vector<ObjectCalcer*> mcalcable;
+ std::vector<ObjectHolder*> mdrawable;
+protected:
+ MovingModeBase( KigPart& doc, KigWidget& v );
+ ~MovingModeBase();
+
+ /**
+ * Subclasses should call this in their constructor, when they know
+ * which objects will be moving around... They are expected to be in
+ * the right order for being calc()'ed...
+ */
+ void initScreen( const std::vector<ObjectCalcer*>& amo );
+
+ // in these functions, subclasses should do the equivalent of
+ // Object::stopMove() and moveTo()... Note that no calc()'ing or
+ // drawing is to be done..
+ virtual void stopMove() = 0;
+ virtual void moveTo( const Coordinate& o, bool snaptogrid ) = 0;
+
+public:
+ void leftReleased( QMouseEvent*, KigWidget* );
+ void leftMouseMoved( QMouseEvent*, KigWidget* );
+ void mouseMoved( QMouseEvent*, KigWidget* );
+};
+
+class MovingMode
+ : public MovingModeBase
+{
+ class Private;
+ Private* d;
+ void stopMove();
+ void moveTo( const Coordinate& o, bool snaptogrid );
+public:
+ MovingMode( const std::vector<ObjectHolder*>& objects, const Coordinate& c,
+ KigWidget&, KigPart& );
+ ~MovingMode();
+};
+
+class PointRedefineMode
+ : public MovingModeBase
+{
+ ObjectHolder* mp;
+ std::vector<ObjectCalcer::shared_ptr> moldparents;
+ const ObjectType* moldtype;
+ MonitorDataObjects* mmon;
+ void stopMove();
+ void moveTo( const Coordinate& o, bool snaptogrid );
+public:
+ PointRedefineMode( ObjectHolder* p, KigPart& d, KigWidget& v );
+ ~PointRedefineMode();
+};
+
+#endif
diff --git a/kig/modes/normal.cc b/kig/modes/normal.cc
new file mode 100644
index 00000000..ecf5f5c1
--- /dev/null
+++ b/kig/modes/normal.cc
@@ -0,0 +1,306 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "normal.h"
+
+#include "../kig/kig_view.h"
+#include "../kig/kig_part.h"
+#include "../kig/kig_document.h"
+#include "../kig/kig_commands.h"
+#include "../objects/object_factory.h"
+#include "../objects/object_imp.h"
+#include "../objects/object_drawer.h"
+#include "../misc/kigpainter.h"
+#include "popup.h"
+#include "moving.h"
+#include "macro.h"
+#include "dragrectmode.h"
+#include "typesdialog.h"
+
+#include <kcursor.h>
+#include <kaction.h>
+#include <kcommand.h>
+#include <klocale.h>
+
+#include <algorithm>
+#include <functional>
+
+using namespace std;
+
+void NormalMode::enableActions()
+{
+ KigMode::enableActions();
+ mdoc.enableConstructActions( true );
+ mdoc.aSelectAll->setEnabled( true );
+ mdoc.aDeselectAll->setEnabled( true );
+ mdoc.aInvertSelection->setEnabled( true );
+ mdoc.aDeleteObjects->setEnabled( true );
+ mdoc.aShowHidden->setEnabled( true );
+ mdoc.aNewMacro->setEnabled( true );
+ mdoc.aConfigureTypes->setEnabled( true );
+ mdoc.history()->updateActions();
+}
+
+void NormalMode::deleteObjects()
+{
+ std::vector<ObjectHolder*> sel( sos.begin(), sos.end() );
+ mdoc.delObjects( sel );
+ sos.clear();
+}
+
+void NormalMode::selectObject( ObjectHolder* o )
+{
+ sos.insert( o );
+}
+
+void NormalMode::selectObjects( const std::vector<ObjectHolder*>& os )
+{
+ // hehe, don't you love this c++ stuff ;)
+ std::for_each( os.begin(), os.end(),
+ std::bind1st(
+ std::mem_fun( &NormalMode::selectObject ), this ) );
+}
+
+void NormalMode::unselectObject( ObjectHolder* o )
+{
+ sos.erase( o );
+}
+
+void NormalMode::clearSelection()
+{
+ sos.clear();
+}
+
+// KigDocumentPopup* NormalMode::popup( KigDocument* )
+// {
+// return 0;
+// }
+
+void NormalMode::showHidden()
+{
+ mdoc.showObjects( mdoc.document().objects() );
+}
+
+void NormalMode::newMacro()
+{
+ DefineMacroMode m( mdoc );
+ mdoc.runMode( &m );
+}
+
+void NormalMode::redrawScreen( KigWidget* w )
+{
+ // unselect removed objects..
+ std::vector<ObjectHolder*> nsos;
+ const std::set<ObjectHolder*> docobjs = mdoc.document().objectsSet();
+ std::set_intersection( docobjs.begin(), docobjs.end(), sos.begin(), sos.end(),
+ std::back_inserter( nsos ) );
+ sos = std::set<ObjectHolder*>( nsos.begin(), nsos.end() );
+ w->redrawScreen( nsos, true );
+ w->updateScrollBars();
+}
+
+void NormalMode::editTypes()
+{
+ TypesDialog d( mdoc.widget(), mdoc );
+ d.exec();
+}
+
+NormalMode::NormalMode( KigPart& d )
+ : BaseMode( d )
+{
+}
+
+NormalMode::~NormalMode()
+{
+}
+
+void NormalMode::dragRect( const QPoint& p, KigWidget& w )
+{
+ DragRectMode d( p, mdoc, w );
+ mdoc.runMode( &d );
+
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+
+ if ( ! d.cancelled() )
+ {
+ std::vector<ObjectHolder*> sel = d.ret();
+
+ if ( d.needClear() )
+ {
+ pter.drawObjects( sos.begin(), sos.end(), false );
+ clearSelection();
+ };
+
+ selectObjects( sel );
+ pter.drawObjects( sel, true );
+ };
+
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+}
+
+void NormalMode::dragObject( const std::vector<ObjectHolder*>& oco, const QPoint& pco,
+ KigWidget& w, bool ctrlOrShiftDown )
+{
+ // first determine what to move...
+ if( sos.find( oco.front() ) == sos.end() )
+ {
+ // the user clicked on something that is currently not
+ // selected... --> we select it, taking the Ctrl- and
+ // Shift-buttons into account...
+ if ( !ctrlOrShiftDown ) clearSelection();
+ selectObject(oco.front());
+ }
+
+ std::vector<ObjectHolder*> sosv( sos.begin(), sos.end() );
+ MovingMode m( sosv, w.fromScreen( pco ), w, mdoc );
+ mdoc.runMode( &m );
+}
+
+void NormalMode::leftClickedObject( ObjectHolder* o, const QPoint&,
+ KigWidget& w, bool ctrlOrShiftDown )
+{
+ KigPainter pter( w.screenInfo(), &w.stillPix, mdoc.document() );
+
+ if ( ! o )
+ {
+ pter.drawObjects( sos.begin(), sos.end(), false );
+ clearSelection();
+ }
+ else if( sos.find( o ) == sos.end() )
+ {
+ // clicked on an object that wasn't selected....
+ if (!ctrlOrShiftDown)
+ {
+ pter.drawObjects( sos.begin(), sos.end(), false );
+ clearSelection();
+ };
+ pter.drawObject( o, true );
+ selectObject( o );
+ }
+ else
+ {
+ // clicked on an object that was selected....
+ pter.drawObject( o, false );
+ unselectObject( o );
+ };
+ w.updateCurPix( pter.overlay() );
+ w.updateWidget();
+}
+
+void NormalMode::midClicked( const QPoint& p, KigWidget& w )
+{
+ ObjectHolder* pto = ObjectFactory::instance()->sensiblePoint( w.fromScreen( p ), mdoc.document(), w );
+ pto->calc( mdoc.document() );
+ mdoc.addObject( pto );
+
+ // refresh the screen...
+ // not necessary, done by addObjects, which calls NormalMode::redrawScreen..
+// w.redrawScreen();
+// w.updateScrollBars();
+}
+
+void NormalMode::rightClicked( const std::vector<ObjectHolder*>& os,
+ const QPoint& plc,
+ KigWidget& w )
+{
+ // saving the current cursor position
+ QPoint pt = QCursor::pos();
+ if( !os.empty() )
+ {
+ ObjectHolder* o = 0;
+ int id = ObjectChooserPopup::getObjectFromList( pt, &w, os );
+ if ( id >= 0 )
+ o = os[id];
+ else
+ return;
+ if( sos.find( o ) == sos.end() )
+ {
+ clearSelection();
+ selectObject( o );
+ };
+ // show a popup menu...
+ std::vector<ObjectHolder*> sosv( sos.begin(), sos.end() );
+ NormalModePopupObjects p( mdoc, w, *this, sosv, plc );
+ p.exec( pt );
+ }
+ else
+ {
+ NormalModePopupObjects p( mdoc, w, *this, std::vector<ObjectHolder*>(), plc );
+ p.exec( pt );
+ };
+}
+
+void NormalMode::mouseMoved( const std::vector<ObjectHolder*>& os,
+ const QPoint& plc,
+ KigWidget& w,
+ bool )
+{
+ w.updateCurPix();
+ if( os.empty() )
+ {
+ w.setCursor( KCursor::arrowCursor() );
+ mdoc.emitStatusBarText( 0 );
+ w.updateWidget();
+ }
+ else
+ {
+ // the cursor is over an object, show object type next to cursor
+ // and set statusbar text
+
+ w.setCursor( KCursor::handCursor() );
+
+ int id = ObjectChooserPopup::getObjectFromList( plc, &w, os, false );
+ QString stat = id == 0 ? os.front()->selectStatement() : i18n( "Which object?" );
+
+ // statusbar text
+ mdoc.emitStatusBarText( stat );
+ KigPainter p( w.screenInfo(), &w.curPix, mdoc.document() );
+
+ // set the text next to the arrow cursor
+ QPoint point = plc;
+ point.setX(point.x()+15);
+
+ p.drawTextStd( point, stat );
+ w.updateWidget( p.overlay() );
+ };
+}
+
+void NormalMode::selectAll()
+{
+ const std::vector<ObjectHolder*> os = mdoc.document().objects();
+ selectObjects( os );
+ mdoc.redrawScreen();
+}
+
+void NormalMode::deselectAll()
+{
+ clearSelection();
+ mdoc.redrawScreen();
+}
+
+void NormalMode::invertSelection()
+{
+ std::vector<ObjectHolder*> os = mdoc.document().objects();
+ std::set<ObjectHolder*> oldsel = sos;
+ clearSelection();
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin();
+ i != os.end(); ++i )
+ if ( oldsel.find( *i ) == oldsel.end() )
+ sos.insert( *i );
+ mdoc.redrawScreen();
+}
diff --git a/kig/modes/normal.h b/kig/modes/normal.h
new file mode 100644
index 00000000..dd51c854
--- /dev/null
+++ b/kig/modes/normal.h
@@ -0,0 +1,74 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODES_NORMAL_H
+#define KIG_MODES_NORMAL_H
+
+#include "base_mode.h"
+
+#include <qpoint.h>
+#include <set>
+
+class NormalMode
+ : public BaseMode
+{
+public:
+ NormalMode( KigPart& );
+ ~NormalMode();
+protected:
+ void dragRect( const QPoint& p, KigWidget& w );
+ void dragObject( const std::vector<ObjectHolder*>& os, const QPoint& pointClickedOn,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void leftClickedObject( ObjectHolder* o, const QPoint& p,
+ KigWidget& w, bool ctrlOrShiftDown );
+ void midClicked( const QPoint& p, KigWidget& w );
+ void rightClicked( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w );
+ void mouseMoved( const std::vector<ObjectHolder*>& os, const QPoint& p, KigWidget& w,
+ bool shiftpressed );
+ void selectAll();
+ void deselectAll();
+ void invertSelection();
+
+protected:
+ /**
+ * Objcects were added..
+ */
+ void redrawScreen( KigWidget* );
+
+ void enableActions();
+
+ void deleteObjects();
+ void showHidden();
+ void newMacro();
+ void editTypes();
+
+public:
+ void selectObject( ObjectHolder* o );
+ void selectObjects( const std::vector<ObjectHolder*>& os );
+ void unselectObject( ObjectHolder* o );
+ void clearSelection();
+
+// KigObjectsPopup* popup( const Objects& os );
+// KigDocumentPopup* popup( KigDocument* );
+protected:
+ /**
+ * selected objects...
+ */
+ std::set<ObjectHolder*> sos;
+};
+
+#endif
diff --git a/kig/modes/popup.cc b/kig/modes/popup.cc
new file mode 100644
index 00000000..b71d9896
--- /dev/null
+++ b/kig/modes/popup.cc
@@ -0,0 +1,1200 @@
+/**
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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 "popup.h"
+#include "popup.moc"
+
+#include "../kig/kig_part.h"
+#include "../kig/kig_document.h"
+#include "../kig/kig_view.h"
+#include "../kig/kig_commands.h"
+#include "../objects/object_imp.h"
+#include "../objects/object_drawer.h"
+#include "../objects/bogus_imp.h"
+#include "../objects/point_imp.h"
+#include "../objects/line_imp.h"
+#include "../objects/other_type.h"
+#include "../objects/object_factory.h"
+#include "../objects/polygon_imp.h"
+#include "../objects/text_imp.h"
+#include "../misc/lists.h"
+#include "../misc/argsparser.h"
+#include "../misc/kigpainter.h"
+#include "../misc/coordinate_system.h"
+#include "../misc/object_constructor.h"
+#include "construct_mode.h"
+#include "normal.h"
+#include "moving.h"
+
+#include <algorithm>
+#include <functional>
+
+#include <qcursor.h>
+#include <qdialog.h>
+#include <qpen.h>
+#include <qregexp.h>
+#include <qvalidator.h>
+
+#include <kaction.h>
+#include <kcolordialog.h>
+#include <kglobal.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#if KDE_IS_VERSION( 3, 1, 90 )
+#include <kinputdialog.h>
+#else
+#include <klineeditdlg.h>
+#endif
+
+#include <config.h>
+
+using namespace std;
+
+class NormalModePopupObjects;
+
+/**
+ * This class is an abstract class. Its role is to fill up the
+ * NormalModePopupObjects with useful actions..
+ */
+class PopupActionProvider
+{
+public:
+ virtual ~PopupActionProvider();
+ /**
+ * add all your entries to menu menu in popup popup. Set nextfree
+ * to the next free index..
+ */
+ virtual void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree ) = 0;
+ /**
+ * try to execute the id'th action you added to menu menu in popup
+ * popup ( first is 0 ). Return true if this action does indeed
+ * belong to you ( is not greater than the number of actions you
+ * added ). Else return false, and subtract the number of actions
+ * you added from id. This requires you to keep a record of how
+ * much actions you added ( unless it's a fixed number, of course
+ * ).
+ */
+ virtual bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m ) = 0;
+};
+
+class BuiltinObjectActionsProvider
+ : public PopupActionProvider
+{
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+class NameObjectActionsProvider
+ : public PopupActionProvider
+{
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+class BuiltinDocumentActionsProvider
+ : public PopupActionProvider
+{
+ int mnumberofcoordsystems;
+ bool misfullscreen;
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+class ObjectConstructorActionsProvider
+ : public PopupActionProvider
+{
+ std::vector<ObjectConstructor*> mctors[NormalModePopupObjects::NumberOfMenus];
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+class PropertiesActionsProvider
+ : public PopupActionProvider
+{
+ // we don't really need NumberOfMenus vectors, but this is the
+ // easiest way to do it, and I'm too lazy to do it properly ;)
+ std::vector<int> mprops[NormalModePopupObjects::NumberOfMenus];
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+class ObjectTypeActionsProvider
+ : public PopupActionProvider
+{
+ int mnoa;
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+
+#ifdef KIG_ENABLE_PYTHON_SCRIPTING
+#include "../scripting/script-common.h"
+#include "../scripting/script_mode.h"
+#include "../scripting/python_type.h"
+
+class ScriptActionsProvider
+ : public PopupActionProvider
+{
+ int mns;
+public:
+ void fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree );
+ bool executeAction( int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& m );
+};
+#endif
+
+NormalModePopupObjects::NormalModePopupObjects( KigPart& part,
+ KigWidget& view,
+ NormalMode& mode,
+ const std::vector<ObjectHolder*>& objs,
+ const QPoint& plc )
+ : KPopupMenu( &view ), mplc( plc ), mpart( part ), mview( view ), mobjs( objs ),
+ mmode( mode ), monlylabels( false )
+{
+ bool empty = objs.empty();
+ bool single = objs.size() == 1;
+ connect( this, SIGNAL( activated( int ) ), this, SLOT( toplevelMenuSlot( int ) ) );
+
+ QString title;
+ if ( empty )
+ title = i18n( "Kig Document" );
+ else if ( single )
+ {
+ if ( !objs[0]->name().isNull() )
+ title = QString::fromLatin1( "%1 %2" ).arg( objs[0]->imp()->type()->translatedName() ).arg( objs[0]->name() );
+ else
+ title = objs[0]->imp()->type()->translatedName();
+ }
+ else
+ title = i18n( "%1 Objects" ).arg( objs.size() );
+ insertTitle( title, 1 );
+
+ if ( !empty )
+ {
+ monlylabels = true;
+ uint i = 0;
+ while ( i < objs.size() && monlylabels )
+ {
+ monlylabels &= objs[i]->imp()->inherits( TextImp::stype() );
+ ++i;
+ }
+ }
+
+ if ( empty )
+ {
+ // provides some diverse stuff like "unhide all", set coordinate
+ // system etc.
+ mproviders.push_back( new BuiltinDocumentActionsProvider() );
+ };
+ // construct an object using these objects and start constructing an
+ // object using these objects
+ mproviders.push_back( new ObjectConstructorActionsProvider() );
+ if ( single )
+ mproviders.push_back( new NameObjectActionsProvider() );
+ if ( ! empty )
+ {
+ // stuff like hide, show, delete, set size, set color..
+ mproviders.push_back( new BuiltinObjectActionsProvider() );
+ // show property as text label -> show menu
+ // and construct property's as objects -> construct menu
+ mproviders.push_back( new PropertiesActionsProvider() );
+ // stuff like "redefine point" for a fixed or constrained point..
+ mproviders.push_back( new ObjectTypeActionsProvider() );
+ }
+#ifdef KIG_ENABLE_PYTHON_SCRIPTING
+ // script action..
+ mproviders.push_back( new ScriptActionsProvider() );
+#endif
+
+ for ( uint i = 0; i < NumberOfMenus; ++i )
+ mmenus[i] = new QPopupMenu( this );
+
+ connect( mmenus[TransformMenu], SIGNAL( activated( int ) ),
+ this, SLOT( transformMenuSlot( int ) ) );
+ connect( mmenus[TestMenu], SIGNAL( activated( int ) ),
+ this, SLOT( testMenuSlot( int ) ) );
+ connect( mmenus[ConstructMenu], SIGNAL( activated( int ) ),
+ this, SLOT( constructMenuSlot( int ) ) );
+ connect( mmenus[StartMenu], SIGNAL( activated( int ) ),
+ this, SLOT( startMenuSlot( int ) ) );
+ connect( mmenus[ShowMenu], SIGNAL( activated( int ) ),
+ this, SLOT( showMenuSlot( int ) ) );
+ connect( mmenus[SetColorMenu], SIGNAL( activated( int ) ),
+ this, SLOT( setColorMenuSlot( int ) ) );
+ connect( mmenus[SetSizeMenu], SIGNAL( activated( int ) ),
+ this, SLOT( setSizeMenuSlot( int ) ) );
+ connect( mmenus[SetStyleMenu], SIGNAL( activated( int ) ),
+ this, SLOT( setStyleMenuSlot( int ) ) );
+ connect( mmenus[SetCoordinateSystemMenu], SIGNAL( activated( int ) ),
+ this, SLOT( setCoordinateSystemMenuSlot( int ) ) );
+
+ for ( int i = 0; i <= NumberOfMenus; ++i )
+ {
+ int nextfree = 10;
+ for ( uint j = 0; j < mproviders.size(); ++j )
+ mproviders[j]->fillUpMenu( *this, i, nextfree );
+ };
+ static const QString menunames[NumberOfMenus] =
+ {
+ i18n( "&Transform" ),
+ i18n( "T&est" ),
+ i18n( "Const&ruct" ),
+ i18n( "&Start" ),
+ i18n( "Add Te&xt Label" ),
+ i18n( "Set Co&lor" ),
+ i18n( "Set &Pen Width" ),
+ i18n( "Set St&yle" ),
+ QString::null,
+ i18n( "Set Coordinate S&ystem" )
+ };
+ static const QString menuicons[NumberOfMenus] =
+ {
+ "centralsymmetry",
+ "test",
+ QString::null,
+ "launch",
+ "kig_text",
+ "color_fill",
+// "colorize",
+ "sizer",
+ "paintbrush",
+ QString::null,
+ QString::null
+ };
+ int index = 1;
+ for ( int i = 0; i < NumberOfMenus; ++i )
+ {
+ if ( mmenus[i]->count() == 0 ) continue;
+ if ( menuicons[i].isNull() )
+ insertItem( menunames[i], mmenus[i], i, index++ );
+ else
+ {
+ KIconLoader* l = part.instance()->iconLoader();
+ QPixmap icon = l->loadIcon( menuicons[i], KIcon::Small, 22, KIcon::DefaultState, 0L, true );
+ insertItem( QIconSet( icon ), menunames[i], mmenus[i], i, index++ );
+ }
+ };
+}
+
+void NormalModePopupObjects::testMenuSlot( int i )
+{
+ activateAction( TestMenu, i );
+}
+
+void NormalModePopupObjects::transformMenuSlot( int i )
+{
+ activateAction( TransformMenu, i );
+}
+
+void NormalModePopupObjects::constructMenuSlot( int i )
+{
+ activateAction( ConstructMenu, i );
+}
+
+void NormalModePopupObjects::startMenuSlot( int i )
+{
+ activateAction( StartMenu, i );
+}
+
+void NormalModePopupObjects::showMenuSlot( int i )
+{
+ activateAction( ShowMenu, i );
+}
+
+void NormalModePopupObjects::toplevelMenuSlot( int i )
+{
+ activateAction( ToplevelMenu, i );
+}
+
+void NormalModePopupObjects::activateAction( int menu, int action )
+{
+ bool done = false;
+ // we need action - 10 cause we called fillUpMenu with nextfree set
+ // to 10 initially..
+ action -= 10;
+ for ( uint i = 0; ! done && i < mproviders.size(); ++i )
+ done = mproviders[i]->executeAction( menu, action, mobjs, *this, mpart, mview, mmode );
+}
+
+NormalModePopupObjects::~NormalModePopupObjects()
+{
+ delete_all ( mproviders.begin(), mproviders.end() );
+}
+
+static const QColor* colors[] =
+{
+ &Qt::blue,
+ &Qt::black,
+ &Qt::gray,
+ &Qt::red,
+ &Qt::green,
+ &Qt::cyan,
+ &Qt::yellow,
+ &Qt::darkRed
+};
+static const int numberofcolors = sizeof( colors ) / sizeof( QColor* );
+
+void BuiltinObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ KIconLoader* l = popup.part().instance()->iconLoader();
+ std::vector<ObjectHolder*> os = popup.objects();
+
+ /*
+ * mp: we want the "show" action to be visible only
+ * if we selected only one object (to be conservative)
+ * and if that object is currently hidden.
+ * conversely for one hidden object we don't want
+ * the "hide" action to be inserted.
+ * in any case we have a fixed 'id' associated
+ * with the two actions.
+ */
+
+ if ( os.size() > 1 || os.front()->shown() )
+ {
+ popup.addAction( menu, i18n( "&Hide" ), nextfree );
+ }
+ if ( os.size() == 1 && !os.front()->shown() )
+ {
+ popup.addAction( menu, i18n( "&Show" ), nextfree+1 );
+ }
+ nextfree += 2;
+ QPixmap p = l->loadIcon( "move", KIcon::Toolbar );
+ popup.addAction( menu, p, i18n( "&Move" ), nextfree++ );
+ p = l->loadIcon( "editdelete", KIcon::Toolbar );
+ popup.addAction( menu, p, i18n( "&Delete" ), nextfree++ );
+ }
+ else if ( menu == NormalModePopupObjects::SetColorMenu )
+ {
+ QPixmap p( 50, 20 );
+ for( const QColor** c = colors; c < colors + numberofcolors; ++c )
+ {
+ p.fill( **c );
+ popup.addAction( menu, p, nextfree++ );
+ }
+ popup.addAction( menu, i18n( "&Custom Color" ), nextfree++ );
+ }
+ else if ( menu == NormalModePopupObjects::SetSizeMenu && !popup.onlyLabels() )
+ {
+ bool point = true;
+ bool samecolor = true;
+ std::vector<ObjectHolder*> os = popup.objects();
+ QColor color = os.front()->drawer()->color();
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ {
+ if ( ! (*i)->imp()->inherits( PointImp::stype() ) )
+ point = false;
+ if ( (*i)->drawer()->color() != color ) samecolor = false;
+ };
+ if ( ! samecolor ) color = Qt::blue;
+ QPixmap p( point ? 20 : 50, 20 );
+ for ( int i = 1; i < 8; ++i )
+ {
+ p.fill( popup.eraseColor() );
+ QPainter ptr( &p );
+ ptr.setPen( QPen( color, 1 ) );
+ ptr.setBrush( QBrush( color, Qt::SolidPattern ) );
+ if ( point )
+ {
+ int size = 2*i;
+ QRect r( ( 20 - size ) / 2, ( 20 - size ) / 2, size, size );
+ ptr.drawEllipse( r );
+ }
+ else
+ {
+ ptr.setPen( QPen( color, -1 + 2*i ) );
+ ptr.drawLine( QPoint( 0, 10 ), QPoint( 50, 10 ) );
+ };
+ ptr.end();
+ popup.addAction( menu, p, nextfree++ );
+ };
+ }
+ else if ( menu == NormalModePopupObjects::SetStyleMenu && !popup.onlyLabels() )
+ {
+ bool samecolor = true;
+ int npoints = 0;
+ int nothers = 0;
+ std::vector<ObjectHolder*> os = popup.objects();
+ QColor color = os.front()->drawer()->color();
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ {
+ if ( (*i)->imp()->inherits( PointImp::stype() ) )
+ npoints++;
+ else
+ nothers++;
+ if ( (*i)->drawer()->color() != color ) samecolor = false;
+ };
+ bool point = ( npoints > nothers );
+ if ( ! samecolor ) color = Qt::blue;
+ if ( point )
+ for ( int i = 0; i < 5; ++i )
+ {
+ QPixmap p( 20, 20 );
+ p.fill( popup.eraseColor() );
+ ScreenInfo si( Rect( -1, -1, 2, 2 ), p.rect() );
+ KigPainter ptr( si, &p, popup.part().document(), false );
+ PointImp pt( Coordinate( 0, 0 ) );
+ ObjectDrawer d( color, -1, true, Qt::SolidLine, i );
+ d.draw( pt, ptr, false );
+ popup.addAction( menu, p, nextfree++ );
+ }
+ else
+ {
+ Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine};
+ for ( int i = 0; i < (int) ( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ); ++i )
+ {
+ QPixmap p( 50, 20 );
+ p.fill( popup.eraseColor() );
+ ScreenInfo si( Rect( -2.5, -1, 5, 2 ), p.rect() );
+ KigPainter ptr( si, &p, popup.part().document(), false );
+ LineImp line( Coordinate( -1, 0 ), Coordinate( 1, 0 ) );
+ Qt::PenStyle ps = penstyles[i];
+ ObjectDrawer d( color, -1, true, ps, 1 );
+ d.draw( line, ptr, false );
+ popup.addAction( menu, p, nextfree++ );
+ };
+ }
+ }
+}
+
+void NameObjectActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ popup.addAction( menu, i18n( "Set &Name..." ), nextfree++ );
+ }
+ else if ( menu == NormalModePopupObjects::ShowMenu )
+ {
+ popup.addAction( menu, i18n( "&Name" ), nextfree++ );
+ }
+}
+
+static void addNameLabel( ObjectCalcer* object, ObjectCalcer* namecalcer, const Coordinate& loc, KigPart& doc )
+{
+ std::vector<ObjectCalcer*> args;
+ args.push_back( namecalcer );
+ const bool namelabelneedsframe = false;
+ ObjectCalcer* attachto = 0;
+ if ( object->imp()->inherits( PointImp::stype() ) ||
+ object->imp()->attachPoint().valid() ||
+ object->imp()->inherits( CurveImp::stype() ) )
+ attachto = object;
+ ObjectHolder* label = ObjectFactory::instance()->attachedLabel(
+ QString::fromLatin1( "%1" ), attachto, loc, namelabelneedsframe, args, doc.document() );
+ doc.addObject( label );
+}
+
+bool NameObjectActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os, NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ if ( id >= 1 )
+ {
+ id -= 1;
+ return false;
+ }
+ assert( os.size() == 1 );
+ QString name = os[0]->name();
+ bool ok;
+ QRegExp re( ".*" );
+ QRegExpValidator* rev = new QRegExpValidator( re, &doc );
+ QString caption = i18n( "Set Object Name" );
+ QString label = i18n( "Set Name of this Object:" );
+#if KDE_IS_VERSION( 3, 1, 90 )
+ name = KInputDialog::getText( caption, label, name, &ok, &w, 0, rev );
+#else
+ name = KLineEditDlg::getText( caption, label, name, &ok, &w, rev );
+#endif
+ if ( ok )
+ {
+ bool justadded = false;
+ ObjectCalcer* namecalcer = os[0]->nameCalcer();
+ if ( !namecalcer )
+ {
+ justadded = true;
+ ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "<unnamed object>" ) ) );
+ os[0]->setNameCalcer( c );
+ namecalcer = c;
+ }
+ assert( dynamic_cast<ObjectConstCalcer*>( namecalcer ) );
+ ObjectConstCalcer* cnamecalcer = static_cast<ObjectConstCalcer*>( os[0]->nameCalcer() );
+ MonitorDataObjects mon( cnamecalcer );
+ cnamecalcer->setImp( new StringImp( name ) );
+ KigCommand* kc = new KigCommand( doc, i18n( "Set Object Name" ) );
+ mon.finish( kc );
+ doc.history()->addCommand( kc );
+
+ // if we just added the name, we add a label to show it to the user.
+ if ( justadded )
+ addNameLabel( os[0]->calcer(), namecalcer,
+// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( QPoint( 5, 0 ) ) ) ),
+ w.fromScreen( popup.plc() ),
+ doc );
+ }
+ return true;
+ }
+ else if ( menu == NormalModePopupObjects::ShowMenu )
+ {
+ if ( id >= 1 )
+ {
+ id -= 1;
+ return false;
+ }
+ assert( os.size() == 1 );
+ ObjectCalcer* namecalcer = os[0]->nameCalcer();
+ if ( !namecalcer )
+ {
+ ObjectConstCalcer* c = new ObjectConstCalcer( new StringImp( i18n( "<unnamed object>" ) ) );
+ os[0]->setNameCalcer( c );
+ namecalcer = c;
+ }
+ addNameLabel( os[0]->calcer(), namecalcer,
+// w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( QPoint( 5, 0 ) ) ) ), doc );
+ w.fromScreen( popup.plc() ), doc );
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool BuiltinObjectActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os, NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& mode )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ if ( id > 3 )
+ {
+ id -= 4;
+ return false;
+ };
+ switch( id )
+ {
+ case 0:
+ // hide the objects..
+ doc.hideObjects( os );
+ break;
+ case 1:
+ // show the objects..
+ doc.showObjects( os );
+ break;
+ case 2:
+ {
+ // move
+ QCursor::setPos( popup.mapToGlobal( QPoint( 0, 0 ) ) );
+ QPoint p = w.mapFromGlobal( QCursor::pos() );
+ Coordinate c = w.fromScreen( p );
+ MovingMode m( os, c, w, doc );
+ doc.runMode( &m );
+ // in this case, we return, cause we don't want objects to be
+ // unselected... ( or maybe we do ? )
+ return true;
+ }
+ case 3:
+ // delete
+ doc.delObjects( os );
+ break;
+ default: assert( false );
+ };
+ mode.clearSelection();
+ return true;
+ }
+ else if ( menu == NormalModePopupObjects::SetColorMenu )
+ {
+ if ( id >= numberofcolors + 1 )
+ {
+ id -= numberofcolors + 1;
+ return false;
+ };
+ QColor color;
+ if ( id < numberofcolors )
+ color = *colors[id];
+ else
+ {
+ if ( os.size() == 1 )
+ color = os.front()->drawer()->color();
+ int result = KColorDialog::getColor( color, &w );
+ if ( result != KColorDialog::Accepted ) return true;
+ }
+ KigCommand* kc = new KigCommand( doc, i18n( "Change Object Color" ) );
+ assert( color.isValid() );
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyColor( color ) ) );
+ doc.history()->addCommand( kc );
+ mode.clearSelection();
+ return true;
+ }
+ else if ( menu == NormalModePopupObjects::SetSizeMenu )
+ {
+ if ( id >= 7 )
+ {
+ id -= 7;
+ return false;
+ };
+
+ KigCommand* kc = new KigCommand( doc, i18n( "Change Object Width" ) );
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyWidth( 1 + 2 * id ) ) );
+ doc.history()->addCommand( kc );
+ mode.clearSelection();
+ return true;
+ }
+ else if ( menu == NormalModePopupObjects::SetStyleMenu )
+ {
+ int npoints = 0;
+ int nothers = 0;
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ {
+ if ( (*i)->imp()->inherits( PointImp::stype() ) )
+ npoints++;
+ else
+ nothers++;
+ };
+ bool point = ( npoints > nothers );
+ int max = point ? 5 : 5;
+ if ( id >= max )
+ {
+ id -= max;
+ return false;
+ };
+
+ if ( point )
+ {
+ KigCommand* kc = new KigCommand( doc, i18n( "Change Point Style" ) );
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ if ( (*i)->imp()->inherits( PointImp::stype() ) )
+ kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyPointStyle( id ) ) );
+ doc.history()->addCommand( kc );
+ mode.clearSelection();
+ return true;
+ }
+ else
+ {
+ Qt::PenStyle penstyles[] = {Qt::SolidLine, Qt::DashLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::DotLine};
+ assert( id < (int)( sizeof( penstyles ) / sizeof( Qt::PenStyle ) ) );
+ Qt::PenStyle p = penstyles[id];
+ KigCommand* kc = new KigCommand( doc, i18n( "Change Object Style" ) );
+ for ( std::vector<ObjectHolder*>::const_iterator i = os.begin(); i != os.end(); ++i )
+ if ( ! (*i)->imp()->inherits( PointImp::stype() ) )
+ kc->addTask( new ChangeObjectDrawerTask( *i, ( *i )->drawer()->getCopyStyle( p ) ) );
+ doc.history()->addCommand( kc );
+ mode.clearSelection();
+ }
+ return true;
+ }
+ else return false;
+}
+
+void ObjectConstructorActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ const KigDocument& d = popup.part().document();
+ const KigWidget& v = popup.widget();
+ typedef ObjectConstructorList::vectype vectype;
+ vectype vec = ObjectConstructorList::instance()->constructors();
+
+ for ( vectype::iterator i = vec.begin(); i != vec.end(); ++i )
+ {
+ bool add = false;
+ if ( popup.objects().empty() )
+ {
+ add = menu == NormalModePopupObjects::StartMenu && ! (*i)->isTransform() && ! (*i)->isTest();
+ }
+ else
+ {
+ int ret = (*i)->wantArgs( getCalcers( popup.objects() ), d, v );
+ if ( ret == ArgsParser::Invalid ) continue;
+ if ( (*i)->isTransform() && popup.objects().size() == 1 ) add = menu == NormalModePopupObjects::TransformMenu;
+ else if ( (*i)->isTest() ) add = menu == NormalModePopupObjects::TestMenu;
+ else if ( ( *i )->isIntersection() ) add = menu == NormalModePopupObjects::ToplevelMenu;
+ else if ( ret == ArgsParser::Complete ) add = menu == NormalModePopupObjects::ConstructMenu;
+ else add = menu == NormalModePopupObjects::StartMenu;
+ };
+ if ( add )
+ {
+ QCString iconfile = (*i)->iconFileName();
+ if ( !iconfile.isEmpty() && !iconfile.isNull() )
+ {
+ QPixmap icon = popup.part().instance()->iconLoader()->loadIcon( iconfile, KIcon::Toolbar, 22, KIcon::DefaultState, 0L, true );
+ popup.addAction( menu, icon, (*i)->descriptiveName(), nextfree++ );
+ }
+ else
+ popup.addAction( menu, (*i)->descriptiveName(), nextfree++ );
+ mctors[menu].push_back( *i );
+ }
+ };
+}
+
+bool ObjectConstructorActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects&,
+ KigPart& doc, KigWidget& w, NormalMode& m )
+{
+ if ( (uint) id >= mctors[menu].size() )
+ {
+ id -= mctors[menu].size();
+ return false;
+ }
+
+ ObjectConstructor* ctor = mctors[menu][id];
+ std::vector<ObjectCalcer*> osc = getCalcers( os );
+ if ( ! os.empty() && ctor->wantArgs( osc, doc.document(), w ) == ArgsParser::Complete )
+ {
+ ctor->handleArgs( osc, doc, w );
+ m.clearSelection();
+ }
+ else
+ {
+ BaseConstructMode* mode = ctor->constructMode( doc );
+ mode->selectObjects( os, w );
+ doc.runMode( mode );
+ delete mode;
+ };
+ return true;
+}
+
+void NormalModePopupObjects::addAction( int menu, const QPixmap& pix, int id )
+{
+ QPopupMenu* m = 0;
+ if ( menu == ToplevelMenu ) m = this;
+ else m = mmenus[menu];
+ int ret = m->insertItem( pix, id );
+ assert( ret == id );
+ // pretend to use this var..
+ (void) ret;
+}
+
+void NormalModePopupObjects::setColorMenuSlot( int i )
+{
+ activateAction( SetColorMenu, i );
+}
+
+void NormalModePopupObjects::setSizeMenuSlot( int i )
+{
+ activateAction( SetSizeMenu, i );
+}
+
+void NormalModePopupObjects::setStyleMenuSlot( int i )
+{
+ activateAction( SetStyleMenu, i );
+}
+
+void NormalModePopupObjects::setCoordinateSystemMenuSlot( int i )
+{
+ activateAction( SetCoordinateSystemMenu, i );
+}
+
+void NormalModePopupObjects::addAction( int menu, const QPixmap& icon, const QString& name, int id )
+{
+ QPopupMenu* m = 0;
+ if ( menu == ToplevelMenu ) m = this;
+ else m = mmenus[menu];
+ int ret = m->insertItem( QIconSet( icon ), name, id );
+ assert( ret == id );
+ // pretend to use this var..
+ (void)ret;
+}
+
+void NormalModePopupObjects::addAction( int menu, const QString& name, int id )
+{
+ QPopupMenu* m = 0;
+ if ( menu == ToplevelMenu ) m = this;
+ else m = mmenus[menu];
+ int ret = m->insertItem( name, id );
+ assert( ret == id );
+ // pretend to use this var..
+ (void)ret;
+}
+
+PopupActionProvider::~PopupActionProvider()
+{
+}
+
+void PropertiesActionsProvider::fillUpMenu( NormalModePopupObjects& popup,
+ int menu, int& nextfree )
+{
+ if ( popup.objects().size() != 1 ) return;
+ ObjectHolder* o = popup.objects()[0];
+ uint np = o->imp()->numberOfProperties();
+ if ( menu != NormalModePopupObjects::ConstructMenu &&
+ menu != NormalModePopupObjects::ShowMenu ) return;
+ for ( uint i = 0; i < np; ++i )
+ {
+ ObjectImp* prop = o->imp()->property( i, popup.part().document() );
+ const char* iconfile = o->imp()->iconForProperty( i );
+ bool add = true;
+ if ( menu == NormalModePopupObjects::ConstructMenu )
+ {
+ // we don't want imp's like DoubleImp, since we can't show them
+ // anyway..
+ add &= ! prop->inherits( BogusImp::stype() );
+ // we don't want to construct PointImp's coordinate property,
+ // since it would construct a point at the same place as its
+ // parent..
+ add &= ! ( o->imp()->inherits( PointImp::stype() ) &&
+ prop->inherits( PointImp::stype() ) );
+ }
+ else if ( menu == NormalModePopupObjects::ShowMenu )
+ add &= prop->canFillInNextEscape();
+ if ( add )
+ {
+ if ( iconfile && *iconfile )
+ {
+ QPixmap pix = popup.part().instance()->iconLoader()->loadIcon( iconfile, KIcon::Toolbar, 22, KIcon::DefaultState, 0L, true );
+ popup.addAction( menu, pix, i18n( o->imp()->properties()[i] ), nextfree++ );
+ }
+ else
+ {
+ popup.addAction( menu, i18n( o->imp()->properties()[i] ), nextfree++ );
+ };
+ mprops[menu-1].push_back( i );
+ };
+ delete prop;
+ };
+}
+
+bool PropertiesActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects& popup,
+ KigPart& doc, KigWidget& w, NormalMode& )
+{
+ if ( menu != NormalModePopupObjects::ConstructMenu &&
+ menu != NormalModePopupObjects::ShowMenu )
+ return false;
+ if ( (uint) id >= mprops[menu - 1].size() )
+ {
+ id -= mprops[menu - 1].size();
+ return false;
+ }
+ int propid = mprops[menu-1][id];
+ assert( os.size() == 1 );
+ ObjectHolder* parent = os[0];
+ if ( menu == NormalModePopupObjects::ShowMenu )
+ {
+ std::vector<ObjectCalcer*> args;
+ args.push_back( new ObjectPropertyCalcer( parent->calcer(), propid ) );
+ args.back()->calc( doc.document() );
+// TODO: recover the cursor position somehow... the following does not work
+// in general...
+// Coordinate c = w.fromScreen( w.mapFromGlobal( popup.mapToGlobal( QPoint( 5, 0 ) ) ) );
+// mp: it seems that we have no idea where to position the label,
+// btw what's the meaning of (5,0)? let the
+// attach method decide what to do... (passing an invalidCoord)
+// /////// Coordinate c = Coordinate::invalidCoord();
+ Coordinate c = w.fromScreen( popup.plc() );
+ ObjectHolder* label = ObjectFactory::instance()->attachedLabel(
+ QString::fromLatin1( "%1" ), parent->calcer(), c,
+ false, args, doc.document() );
+ doc.addObject( label );
+ }
+ else
+ {
+ ObjectHolder* h = new ObjectHolder(
+ new ObjectPropertyCalcer( parent->calcer(), propid ) );
+ h->calc( doc.document() );
+ doc.addObject( h );
+ };
+ return true;
+}
+
+void ObjectTypeActionsProvider::fillUpMenu(
+ NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ if ( popup.objects().size() != 1 ) return;
+ if ( menu != NormalModePopupObjects::ToplevelMenu ) return;
+ ObjectHolder* to = popup.objects()[0];
+ ObjectTypeCalcer* c = dynamic_cast<ObjectTypeCalcer*>( to->calcer() );
+ if ( ! c ) return;
+ const ObjectType* t = c->type();
+
+ QStringList l = t->specialActions();
+ mnoa = l.count();
+ for ( int i = 0; i < mnoa; ++i )
+ popup.addAction( menu, l[i], nextfree++ );
+}
+
+bool ObjectTypeActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects&,
+ KigPart& doc, KigWidget& w, NormalMode& m )
+{
+ if ( menu != NormalModePopupObjects::ToplevelMenu ) return false;
+ if ( id >= mnoa )
+ {
+ id -= mnoa;
+ return false;
+ }
+ assert( os.size() == 1 );
+ ObjectTypeCalcer* oc = dynamic_cast<ObjectTypeCalcer*>( os[0]->calcer() );
+ assert( oc );
+
+ oc->type()->executeAction( id, *os[0], *oc, doc, w, m );
+ return true;
+}
+
+void BuiltinDocumentActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ popup.addAction( menu, i18n( "U&nhide All" ), nextfree++ );
+ popup.part().action( "view_zoom_in" )->plug( &popup );
+ popup.part().action( "view_zoom_out" )->plug( &popup );
+ popup.part().action( "fullscreen" )->plug( &popup );
+ nextfree += 3;
+ }
+ else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu )
+ {
+ int idoffset = nextfree;
+ QStringList l = CoordinateSystemFactory::names();
+ mnumberofcoordsystems = l.count();
+ for ( uint i = 0; i < l.count(); ++i )
+ popup.addAction( menu, l[i], nextfree++ );
+ int current = popup.part().document().coordinateSystem().id();
+ popup.setChecked( menu, idoffset + current, true );
+ }
+}
+
+bool BuiltinDocumentActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>&,
+ NormalModePopupObjects&,
+ KigPart& doc, KigWidget&, NormalMode& m )
+{
+ if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ kdDebug() << "id: " << id << endl;
+ if ( id == 0 )
+ {
+ doc.showHidden();
+ m.clearSelection();
+ return true;
+ }
+ id -= 1;
+ return false;
+ }
+ else if ( menu == NormalModePopupObjects::SetCoordinateSystemMenu )
+ {
+ if ( id >= mnumberofcoordsystems )
+ {
+ id -= mnumberofcoordsystems;
+ return false;
+ };
+ CoordinateSystem* sys = CoordinateSystemFactory::build( id );
+ assert( sys );
+ doc.history()->addCommand( KigCommand::changeCoordSystemCommand( doc, sys ) );
+ m.clearSelection();
+ return true;
+ }
+ else return false;
+}
+
+void NormalModePopupObjects::setChecked( int menu, int n, bool checked )
+{
+ mmenus[menu]->setItemChecked( n, checked );
+}
+
+#ifdef KIG_ENABLE_PYTHON_SCRIPTING
+/**
+ * this is a local function that looks for a python script associated
+ * to a clicked object
+ */
+static ObjectTypeCalcer* getPythonExecuteTypeFromCalcer( ObjectCalcer* o )
+{
+ ObjectTypeCalcer* oc = dynamic_cast<ObjectTypeCalcer *>( o );
+ if ( !oc ) return 0;
+ const PythonExecuteType* pythonexec = dynamic_cast<const PythonExecuteType*>( oc->type() );
+ if ( pythonexec ) return oc;
+
+ return 0;
+}
+
+void ScriptActionsProvider::fillUpMenu( NormalModePopupObjects& popup, int menu, int& nextfree )
+{
+ if ( menu == NormalModePopupObjects::StartMenu )
+ {
+ KIconLoader* l = popup.part().instance()->iconLoader();
+ QPixmap p = l->loadIcon( ScriptType::icon( ScriptType::Python ), KIcon::Toolbar, 22, KIcon::DefaultState, 0L, true );
+ popup.addAction( menu, p, i18n( "Python Script" ), nextfree++ );
+ mns++;
+ }
+ else if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ if ( !popup.objects().empty() &&
+ getPythonExecuteTypeFromCalcer( popup.objects().front()->calcer() ) )
+ {
+ popup.addAction( menu, i18n( "Edit Script..." ), nextfree );
+ }
+ nextfree++;
+ }
+}
+
+bool ScriptActionsProvider::executeAction(
+ int menu, int& id, const std::vector<ObjectHolder*>& os,
+ NormalModePopupObjects&, KigPart& doc, KigWidget& w, NormalMode& mode )
+{
+ if ( menu == NormalModePopupObjects::StartMenu )
+ {
+ if ( id == 0 )
+ {
+ ScriptCreationMode m( doc );
+ m.setScriptType( ScriptType::Python );
+ if ( os.size() > 0 )
+ {
+ mode.clearSelection();
+ m.addArgs( os, w );
+ m.goToCodePage();
+ }
+ doc.runMode( &m );
+ return true;
+ }
+ else
+ {
+ id -= mns;
+ }
+ }
+ else if ( menu == NormalModePopupObjects::ToplevelMenu )
+ {
+ if ( id == 0 )
+ {
+ ObjectTypeCalcer* oc = getPythonExecuteTypeFromCalcer( os.front()->calcer() );
+ if ( oc )
+ {
+ ScriptEditMode m( oc, doc );
+ m.setScriptType( ScriptType::Python );
+ doc.runMode( &m );
+ }
+ return true;
+ }
+ else
+ {
+ id -= 1;
+ }
+ }
+
+ return false;
+}
+#endif
+
+int ObjectChooserPopup::getObjectFromList( const QPoint& p, KigWidget* w,
+ const std::vector<ObjectHolder*>& objs,
+ bool givepopup )
+{
+ int size = objs.size();
+
+ // no objects
+ if ( size == 0 )
+ return -1;
+
+ int id = -1;
+
+ int numpoints = 0;
+ int numpolygons = 0;
+ int numothers = 0;
+
+ for ( std::vector<ObjectHolder*>::const_iterator i = objs.begin();
+ i != objs.end(); ++i )
+ {
+ if ( (*i)->imp()->inherits( PointImp::stype() ) ) numpoints++;
+ else if ( (*i)->imp()->inherits( PolygonImp::stype() ) ) numpolygons++;
+ else numothers++;
+ }
+
+ // simply cases:
+ // - only 1 point ( and eventually other objects )
+ // - no points and an object which is not a polygon
+ // - only one object
+ // FIXME: we assume that our objects are sorted ( points, others, polygons )!
+ if ( ( numpoints == 1 ) ||
+ ( ( numpoints == 0 ) && ( numothers == 1 ) ) ||
+ ( size == 1 ) )
+ id = 0;
+ else
+ {
+ if ( givepopup )
+ {
+ ObjectChooserPopup* ppp = new ObjectChooserPopup( p, *w, objs );
+ ppp->exec( QCursor::pos() );
+
+ id = ppp->mselected;
+
+ delete ppp;
+ ppp = 0;
+ }
+ else
+ {
+ // we don't want to show a popup to the user, so let's give a
+ // value > 0 to indicate that it's not the first
+ id = 1;
+ }
+ }
+// kdDebug() << "numpoints: " << numpoints << endl
+// << "numothers: " << numothers << endl
+// << "numpolygons: " << numpolygons << endl
+// << "id: " << id << endl;
+
+ return id;
+}
+
+ObjectChooserPopup::ObjectChooserPopup( const QPoint& p, KigWidget& view,
+ const std::vector<ObjectHolder*>& objs )
+ : KPopupMenu(), mplc( p ), mview( view ), mobjs( objs ), mselected( -1 )
+{
+ for ( uint i = 0; i < mobjs.size(); i++ )
+ {
+ insertItem( !mobjs[i]->name().isEmpty()
+ ? QString::fromLatin1( "%1 %2" ).arg( mobjs[i]->imp()->type()->translatedName() ).arg( mobjs[i]->name() )
+ : mobjs[i]->imp()->type()->translatedName(),
+ i );
+ }
+
+ connect( this, SIGNAL( activated( int ) ), this, SLOT( actionActivatedSlot( int ) ) );
+}
+
+ObjectChooserPopup::~ObjectChooserPopup()
+{
+}
+
+void ObjectChooserPopup::actionActivatedSlot( int which )
+{
+ mselected = which;
+}
diff --git a/kig/modes/popup.h b/kig/modes/popup.h
new file mode 100644
index 00000000..405bcee6
--- /dev/null
+++ b/kig/modes/popup.h
@@ -0,0 +1,153 @@
+/**
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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
+**/
+
+#ifndef KIG_MODES_POPUP_H
+#define KIG_MODES_POPUP_H
+
+#include <kpopupmenu.h>
+
+#include <vector>
+
+class KigDocument;
+class KigPart;
+class KigWidget;
+class NormalMode;
+class PopupActionProvider;
+class ObjectHolder;
+
+/**
+ * This is the popup menu that appears when you click on selected
+ * objects in NormalMode.. It's quite complex, since it has to fetch
+ * a lot of information from various places, and dispatch it again
+ * when the user selects something.
+ * Update: I'm also using it for when you clicked on an empty space in
+ * the document, because the difference between the two cases is not
+ * that important, and this class is generic enough to handle both
+ * cases.. When this is the case, mobjs is empty, some
+ * PopupActionProviders are disabled, and some others enabled..
+ */
+class NormalModePopupObjects
+ : public KPopupMenu
+{
+ Q_OBJECT
+
+public:
+ NormalModePopupObjects( KigPart& part, KigWidget& view,
+ NormalMode& mode,
+ const std::vector<ObjectHolder*>& objs, const QPoint& p );
+ ~NormalModePopupObjects();
+
+ // the different "menu's", the toplevel is considered as just
+ // another menu..
+ enum { TransformMenu = 0, TestMenu, ConstructMenu, StartMenu, ShowMenu,
+ SetColorMenu, SetSizeMenu, SetStyleMenu, ToplevelMenu,
+ SetCoordinateSystemMenu, NumberOfMenus };
+
+ // used by the PopupActionProvider's to add actions to us..
+ void addAction( int menu, const QString& name, int id );
+ void addAction( int menu, const QPixmap& icon, const QString& name, int id );
+ void addAction( int menu, const QPixmap& pix, int id );
+
+ /**
+ * set the checked state of the \p n 'th item in \p menu to \p checked ..
+ */
+ void setChecked( int menu, int n, bool checked );
+
+ std::vector<ObjectHolder*> objects() const { return mobjs; }
+ KigPart& part() { return mpart; }
+ KigWidget& widget() { return mview; }
+ QPoint plc() { return mplc; }
+
+ bool onlyLabels() const { return monlylabels; }
+
+protected:
+ void activateAction( int menu, int action );
+
+private slots:
+ void transformMenuSlot( int );
+ void testMenuSlot( int );
+ void constructMenuSlot( int );
+ void startMenuSlot( int );
+ void showMenuSlot( int );
+ void setColorMenuSlot( int );
+ void setSizeMenuSlot( int );
+ void setStyleMenuSlot( int );
+ void toplevelMenuSlot( int );
+ void setCoordinateSystemMenuSlot( int );
+
+protected:
+ QPoint mplc;
+ KigPart& mpart;
+ KigWidget& mview;
+ std::vector<ObjectHolder*> mobjs;
+ NormalMode& mmode;
+
+ std::vector<PopupActionProvider*> mproviders;
+
+ QPopupMenu* mmenus[NumberOfMenus];
+
+private:
+ bool monlylabels;
+};
+
+/**
+ * This class is useful to choose one object from a list of some, by
+ * querying the user via popup menu.
+ *
+ * You can't use this class directly, but these's a convenience method.
+ */
+class ObjectChooserPopup
+ : public KPopupMenu
+{
+ Q_OBJECT
+
+public:
+ /**
+ * Get the index of the choosen object from a list of objects.
+ *
+ * \param p is the point whene executre the popup
+ * \param w is the pointer to a KigWidget
+ * \param objs is the vector with the objects to chose from
+ * \param givepopup true means that we have to show a popup to the user
+ *
+ * \return the index of the chosen element ( starting from 0 ), or -1
+ * if none was selected.
+ */
+ static int getObjectFromList( const QPoint& p, KigWidget* w,
+ const std::vector<ObjectHolder*>& objs,
+ bool givepopup = true );
+
+protected:
+ ObjectChooserPopup( const QPoint& p, KigWidget& view,
+ const std::vector<ObjectHolder*>& objs );
+ ~ObjectChooserPopup();
+
+protected slots:
+ void actionActivatedSlot( int );
+
+protected:
+ QPoint mplc;
+ KigWidget& mview;
+ std::vector<ObjectHolder*> mobjs;
+
+ int mselected;
+};
+
+#endif
diff --git a/kig/modes/textlabelwizard.cc b/kig/modes/textlabelwizard.cc
new file mode 100644
index 00000000..803ca819
--- /dev/null
+++ b/kig/modes/textlabelwizard.cc
@@ -0,0 +1,95 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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 "textlabelwizard.h"
+#include "textlabelwizard.moc"
+
+#include "label.h"
+#include "linkslabel.h"
+
+#include <qtextedit.h>
+#include <kapplication.h>
+
+#include <qlayout.h>
+
+TextLabelWizard::TextLabelWizard( QWidget* parent, TextLabelModeBase* mode )
+ : TextLabelWizardBase( parent, "TextLabelWizard", false ), mmode( mode )
+{
+ connect( labelTextInput, SIGNAL( textChanged() ),
+ SLOT( textChanged() ) );
+ connect( myCustomWidget1, SIGNAL( linkClicked( int ) ),
+ SLOT( linkClicked( int ) ) );
+ connect( this, SIGNAL( helpClicked() ),
+ this, SLOT( slotHelpClicked() ) );
+ labelTextInput->setFocus();
+}
+
+TextLabelWizard::~TextLabelWizard()
+{
+}
+
+void TextLabelWizard::back()
+{
+ if ( currentPage() == select_arguments_page )
+ {
+ mmode->enterTextPageEntered();
+ }
+ TextLabelWizardBase::back();
+}
+
+void TextLabelWizard::next()
+{
+ if ( currentPage() == enter_text_page )
+ {
+ mmode->selectArgumentsPageEntered();
+ }
+ TextLabelWizardBase::next();
+}
+
+void TextLabelWizard::reject()
+{
+ TextLabelWizardBase::reject();
+ mmode->cancelPressed();
+}
+
+void TextLabelWizard::accept()
+{
+ mmode->finishPressed();
+}
+
+void TextLabelWizard::textChanged()
+{
+ mmode->labelTextChanged();
+}
+
+void TextLabelWizard::linkClicked( int which )
+{
+ mmode->linkClicked( which );
+}
+
+void TextLabelWizard::relayoutArgsPage()
+{
+ select_arguments_pageLayout->activate();
+ repaint();
+}
+
+void TextLabelWizard::slotHelpClicked()
+{
+ kapp->invokeHelp( QString::fromLatin1( "text-labels" ),
+ QString::fromLatin1( "kig" ) );
+}
+
diff --git a/kig/modes/textlabelwizard.h b/kig/modes/textlabelwizard.h
new file mode 100644
index 00000000..787e0803
--- /dev/null
+++ b/kig/modes/textlabelwizard.h
@@ -0,0 +1,46 @@
+// Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+// 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.
+
+#ifndef KIG_MODES_TEXTLABELWIZARD_H
+#define KIG_MODES_TEXTLABELWIZARD_H
+
+#include "textlabelwizardbase.h"
+
+class TextLabelModeBase;
+
+class TextLabelWizard : public TextLabelWizardBase
+{
+ Q_OBJECT
+public:
+ TextLabelWizard( QWidget* parent, TextLabelModeBase* mode );
+ ~TextLabelWizard();
+
+ void back();
+ void next();
+ void reject();
+ void accept();
+
+ void relayoutArgsPage();
+private slots:
+ void textChanged();
+ void linkClicked( int which );
+ void slotHelpClicked();
+private:
+ TextLabelModeBase* mmode;
+};
+
+#endif // TEXTLABELWIZARD_H
diff --git a/kig/modes/textlabelwizardbase.ui b/kig/modes/textlabelwizardbase.ui
new file mode 100644
index 00000000..4e195b0d
--- /dev/null
+++ b/kig/modes/textlabelwizardbase.ui
@@ -0,0 +1,113 @@
+<!DOCTYPE UI><UI version="3.1.2" stdsetdef="1">
+<class>TextLabelWizardBase</class>
+<widget class="QWizard">
+ <property name="name">
+ <cstring>TextLabelWizardBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>488</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Construct Label</string>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>enter_text_page</cstring>
+ </property>
+ <attribute name="title">
+ <string>Enter Label Text</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>enterTextLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Enter the text for your label here and press "Next".
+If you want to show variable parts, then put %1, %2, ... at the appropriate places (e.g. "This segment is %1 units long.").</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QTextEdit">
+ <property name="name">
+ <cstring>labelTextInput</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>needFrameCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>Show text in a frame</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>select_arguments_page</cstring>
+ </property>
+ <attribute name="title">
+ <string>Select Arguments</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>selectArgsLabel</cstring>
+ </property>
+ <property name="text">
+ <string>Now select the argument(s) you need. For every argument, click on it, select an object and a property in the Kig window, and click finish when you are done...</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="LinksLabel">
+ <property name="name">
+ <cstring>myCustomWidget1</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+</widget>
+<customwidgets>
+ <customwidget>
+ <class>LinksLabel</class>
+ <header location="local">linkslabel.h</header>
+ <sizehint>
+ <width>-1</width>
+ <height>-1</height>
+ </sizehint>
+ <container>0</container>
+ <sizepolicy>
+ <hordata>5</hordata>
+ <verdata>5</verdata>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ <pixmap>image0</pixmap>
+ </customwidget>
+</customwidgets>
+<images>
+ <image name="image0">
+ <data format="XPM.GZ" length="4462">789c9d97c76e24490e86effd1442f3d65870d2451a0ce6206f5adeb4cc620f8c34f2553225b5a4c1befb46927fe6a1d4c0ccac4287fa8a0c26834193f5dbb785b3fd9d856fbf7d799ec9ecba5ea8afe469e15bf3727ffffeeffffcf1e797af49b2d0ffc7d142f2f55f5fbe1ecc16ea85dde9a4ed81290045faa77ca49cf4ab67ba1e3953969173651ab9d4fdf1c8a27c3872ad7c3c72d3b32c2a67c3f3444636fbef23eb7e590267e68fcc4656395d8dacf6d938ef97eaef289781cddebdb2846fccff44b989ba58e3411f3dc75158e6df1d3889539517ca49bf54fe43398d1dec4f46567f685fd9c539f43fc025f80c1c3ce8d93f28e77185f8bf0c6cfae4c0b5f9c3c6e5c0542a4b5876fe13708df39d2bd7716372aa8c93c4e4723bb2f977aadc26ceec4bdb7310e6b0bfab9c2445ecd49f1370694cebca65d260ffa6711a41aef14d24e94cee6be3348e0ae5e9c8765f07ca3e8db17f0f9c825794eb3489351fe9bb7217e4969f29388bd51ee9fda5715a19730696b852fea95c6471647ca95cf64bcf43e0cef4657b647bfe6acf213d6bb32f9a9f5992b5a64f9a8f990b6cf9ecc15d6cf9acf6b2da55a8a75cb973dee4b2d1b38b5c05de02434e87e01aacfb351df5bebddea74b5c67f9c795711ea15e357e2ecde358fb87efc0a867df8cac728a074e62e527706afb59f3cf6583be5c28bb3c35f693812d1fbdc6dbe57966fec932d899ffa4f7e38adca17e34beaeca4b9c271a18f1d5fc739257b0d70d9c68be7bed7fcee7827ab91cd8e4740cf6b19d4ffb87ab07b9bf516e72d4a3ac821b9cef6e60d84f47367ded2fae1d9f7704f6163f79000ffde27660f387ed3c5dbf54dfeebb0bf6acbe6b706bfa5ef32f8f8b18f5bf0f463f20edb77956a4e68fbc80b3c4facd163847be6bfde72ec86dbeac82715fbc0286be683cf3bc081d44f7df80d344fb0b6b7de64581fb916765297263d6fccd9b7ee97e566e8b06cfdb1f59cf2bda2f8bbc2c11df0c5c41aefdb328ca22b1feb0012eedbce24736f91b18fb796d64eb87cb60817dcdafb07d906bfd14d22f659d8785ef97b2f6d7b2df6ef1d6fb2babaac6f92e8c25b27ecc1f239b7f3a5fca5a8678ea7c2d9bc0e6ef1238b3fca2c7814d5f4cbf9334b5f833384bed3c7a5f5514f4adbe2ec07962e7590457f06f6f649b977afe2a16f42f5e070bfc591e18f7a5f1a812a9e0df39d827da4fbd8c6ccfd7785569bf945f953371a9d5a3de67950bfa2d75c63eb2fb15bdcfaaf011e6c7263846bf8f4636f91618f3c7d3c0f047fb69550efab2074e12bd6fd27957553ec33c5b043bcc7f9d0795f818fdb501a3df8ae673e507ff69021eea37063bc45ffb73550736ff36c0a84f3e0317a86f8b5f139e6ffe1f821de6d9127898ff3be00a7c3ab2cd03e3d697560ff40016e47b3bb2e96bbd559d8f32bbff4b7065f193042c98873acf240af6adbf3c83c5f2954bb0c7bcd77c107d81d2fdebc63e33ff640aaecc9e1c8151df5c803dfaadc64b52dfa03ed64636ffb4ff4b2867f453ede7227586fcd3f9264ded91fffafe236d5da37fe83c91ceb7b9e5b7f6731ff92ed7f747d6fbf7e185cf58347e3e6932e47b3430fa893edf87d795c2fc3f003b67f5f902cec17abfde0dfa3c053b3c5ffb832fc2eb8fddcf233887fc195c801f46b6f3cdc02558fba72f7d2d1a7f7e321ee58fe0cad86bbff24dd3e2fe74fef836b0c6eb60d62fa6bf5e07b3419f853dd7dc70fb8bd5f1255fd90ed30f9f3c5ff30ddff21ddff384a7fcc08ffcc4cf61cdf8855ff9e79c7e1db4dff89d3f7891977899577895d7789d377893b7f83b6fcfe937bc13b477798ff7f9800ff928ac633ee11f7cca6761d7f99c7e1b3cb908da11c7413be1943376e153cc39175c72f549ff9e17c31744429e6a6aa8a58e2ee98aaee9866e7f617fc24b7417a4f734a1293dd0233dd133cd8285177aa5f9f3b63ca5377aa78f607b919668995682e62aadd17ab0b1419b9ff41f682b48bed336edd02eed05ed7d5ea3033a0cdf1ed1f127fd273ae123fa41a774a6b685cee982228a837e42e927fd47caf8985c38651eb40b2ac38e4a5842658a97fab33fd248cb87d2c9a55cc9b5dcc82d1fc99ddccb44a6f230af2f8ff224cf417f262ff22a3fe54ddee543166549966545567f617f4dd66523dc6b2c9bb225df655b7682f692ecca9eeccfe97772c09b722847722c27c1f3eb70f66bf9116c9fca999ccbc59cfe25bf4a143a5ef8992561324a78bd92522acf9ebc78efe7cf7b153276db37bef59dbff457fedadff85b7f27abfede4ffcd4cf9ff76faeff4fffefeff8c7f5fedfdfbffc0fa355c495</data>
+ </image>
+</images>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>linkslabel.h</includehint>
+</includehints>
+</UI>
diff --git a/kig/modes/typesdialog.cpp b/kig/modes/typesdialog.cpp
new file mode 100644
index 00000000..67621c20
--- /dev/null
+++ b/kig/modes/typesdialog.cpp
@@ -0,0 +1,282 @@
+/**
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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 "typesdialog.h"
+#include "typesdialog.moc"
+
+#include "edittype.h"
+#include "../kig/kig_part.h"
+#include "../misc/guiaction.h"
+#include "../misc/object_constructor.h"
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <kstdguiitem.h>
+
+#include <qfile.h>
+#include <qpixmap.h>
+#include <qstringlist.h>
+#include <qtextstream.h>
+
+#include <algorithm>
+#include <vector>
+
+class MacroListElement
+ : public QListViewItem
+{
+ Macro* macro;
+public:
+ MacroListElement( KListView* lv, Macro* m );
+ Macro* getMacro() const { return macro; }
+};
+
+MacroListElement::MacroListElement( KListView* lv, Macro* m )
+ : QListViewItem( lv, QString::null, m->action->descriptiveName(), m->action->description() ),
+ macro( m )
+{
+}
+
+TypesDialog::TypesDialog( QWidget* parent, KigPart& part )
+ : TypesDialogBase( parent, "types_dialog", true ), mpart( part )
+{
+ // improving GUI look'n'feel...
+ buttonHelp->setGuiItem( KStdGuiItem::help() );
+ buttonOk->setGuiItem( KStdGuiItem::ok() );
+ buttonCancel->setGuiItem( KStdGuiItem::cancel() );
+ il = part.instance()->iconLoader();
+ buttonEdit->setIconSet( QIconSet( il->loadIcon( "edit", KIcon::Small ) ) );
+ buttonRemove->setIconSet( QIconSet( il->loadIcon( "editdelete", KIcon::Small ) ) );
+ buttonExport->setIconSet( QIconSet( il->loadIcon( "fileexport", KIcon::Small ) ) );
+ buttonImport->setIconSet( QIconSet( il->loadIcon( "fileimport", KIcon::Small ) ) );
+
+ typeList->setColumnWidth( 0, 22 );
+ typeList->setColumnWidth( 1, 140 );
+ typeList->setColumnWidth( 2, 240 );
+
+ // loading macros...
+ loadAllMacros();
+
+ popup = new QPopupMenu( this );
+ popup->insertItem( SmallIcon( "edit" ), i18n( "&Edit..." ), this, SLOT( editType() ) );
+ popup->insertItem( SmallIcon( "editdelete" ), i18n( "&Delete" ), this, SLOT( deleteType() ) );
+ popup->insertSeparator();
+ popup->insertItem( SmallIcon( "fileexport" ), i18n( "E&xport..." ), this, SLOT( exportType() ) );
+
+ // saving types
+ part.saveTypes();
+}
+
+QListViewItem* TypesDialog::newListItem( Macro* m )
+{
+ MacroListElement* e = new MacroListElement( typeList, m );
+ QCString ifn = m->action->iconFileName();
+ if ( !ifn.isNull() )
+ {
+ QPixmap p = il->loadIcon( ifn, KIcon::Small );
+ e->setPixmap( 0, p );
+ }
+ return e;
+}
+
+TypesDialog::~TypesDialog()
+{
+}
+
+void TypesDialog::helpSlot()
+{
+ kapp->invokeHelp( QString::fromLatin1( "working-with-types" ),
+ QString::fromLatin1( "kig" ) );
+}
+
+void TypesDialog::okSlot()
+{
+ mpart.saveTypes();
+ mpart.deleteTypes();
+ mpart.loadTypes();
+ accept();
+}
+
+void TypesDialog::deleteType()
+{
+ std::vector<QListViewItem*> items;
+ std::vector<Macro*> selectedTypes;
+ QListViewItemIterator it( typeList );
+ while ( it.current() ) {
+ if ( ( it.current() )->isSelected() )
+ {
+ items.push_back( it.current() );
+ selectedTypes.push_back( static_cast<MacroListElement*>( it.current() )->getMacro() );
+ }
+ ++it;
+ }
+ if (selectedTypes.empty()) return;
+ QStringList types;
+ for ( std::vector<Macro*>::iterator j = selectedTypes.begin();
+ j != selectedTypes.end(); ++j )
+ types << ( *j )->action->descriptiveName();
+ if ( KMessageBox::warningContinueCancelList( this,
+ i18n( "Are you sure you want to delete this type?",
+ "Are you sure you want to delete these %n types?", selectedTypes.size() ),
+ types, i18n("Are You Sure?"), KStdGuiItem::cont(),
+ "deleteTypeWarning") == KMessageBox::Cancel )
+ return;
+ for ( std::vector<QListViewItem*>::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ int appel = typeList->itemIndex(*i);
+ assert (appel != -1);
+ delete *i;
+ };
+ for ( std::vector<Macro*>::iterator j = selectedTypes.begin();
+ j != selectedTypes.end(); ++j)
+ MacroList::instance()->remove( *j );
+}
+
+void TypesDialog::exportType()
+{
+ std::vector<Macro*> types;
+ QListViewItemIterator it( typeList );
+ while ( it.current() ) {
+ if ( ( it.current() )->isSelected() )
+ {
+ types.push_back( static_cast<MacroListElement*>( it.current() )->getMacro() );
+ }
+ ++it;
+ }
+ if (types.empty()) return;
+ QString file_name = KFileDialog::getSaveFileName(":macro", i18n("*.kigt|Kig Types Files\n*|All Files"), this, i18n( "Export Types" ) );
+ if ( file_name.isNull() )
+ return;
+ QFile fi( file_name );
+ if ( fi.exists() )
+ if ( KMessageBox::warningContinueCancel( this, i18n( "The file \"%1\" already exists. "
+ "Do you wish to overwrite it?" ).arg( fi.name() ),
+ i18n( "Overwrite File?" ), i18n("Overwrite") ) == KMessageBox::Cancel )
+ return;
+ MacroList::instance()->save( types, file_name );
+}
+
+void TypesDialog::importTypes()
+{
+ QStringList file_names =
+ KFileDialog::getOpenFileNames(":importTypes", i18n("*.kigt|Kig Types Files\n*|All Files"), this, i18n( "Import Types" ));
+
+ std::vector<Macro*> macros;
+
+ for ( QStringList::Iterator i = file_names.begin();
+ i != file_names.end(); ++i)
+ {
+ std::vector<Macro*> nmacros;
+ bool ok = MacroList::instance()->load( *i, nmacros, mpart );
+ if ( ! ok )
+ continue;
+ std::copy( nmacros.begin(), nmacros.end(), std::back_inserter( macros ) );
+ };
+ MacroList::instance()->add( macros );
+
+ for ( uint i = 0; i < macros.size(); ++i )
+ typeList->insertItem( newListItem( macros[i] ) );
+}
+
+QString TypesDialog::fetchIconFromListItem( QListViewItem* i )
+{
+ QListViewItemIterator it( typeList );
+ Macro* ai = static_cast<MacroListElement*>( i )->getMacro();
+ while ( it.current() ) {
+ if ( ( it.current() )->isSelected() )
+ {
+ Macro* ait = static_cast<MacroListElement*>( it.current() )->getMacro();
+ if ( ai == ait )
+ {
+ return ai->ctor->iconFileName( true );
+ }
+ }
+ ++it;
+ }
+ return "gear";
+}
+
+void TypesDialog::editType()
+{
+ std::vector<QListViewItem*> items;
+ QListViewItemIterator it( typeList );
+ while ( it.current() ) {
+ if ( ( it.current() )->isSelected() )
+ items.push_back( it.current() );
+ ++it;
+ }
+ if ( items.size() == 0 )
+ return;
+ if ( items.size() > 1 )
+ {
+ KMessageBox::sorry( this,
+ i18n( "There is more than one type selected. You can "
+ "only edit one type at a time. Please select "
+ "only the type you want to edit and try again." ),
+ i18n( "More Than One Type Selected" ) );
+ return;
+ }
+ QListViewItem* i = items[0];
+ EditType* d = new EditType( this, i->text( 1 ), i->text( 2 ), fetchIconFromListItem( i ) );
+ if ( d->exec() )
+ {
+ QString newname = d->name();
+ QString newdesc = d->description();
+ QString newicon = d->icon();
+
+ Macro* oldmacro = static_cast<MacroListElement*>( i )->getMacro();
+// mpart.unplugActionLists();
+ oldmacro->ctor->setName( newname );
+ oldmacro->ctor->setDescription( newdesc );
+ QCString ncicon( newicon.utf8() );
+ oldmacro->ctor->setIcon( ncicon );
+// mpart.plugActionLists();
+
+ typeList->clear();
+
+ loadAllMacros();
+ }
+ delete d;
+}
+
+void TypesDialog::contextMenuRequested( QListViewItem*, const QPoint& p, int )
+{
+ popup->exec( p );
+}
+
+void TypesDialog::loadAllMacros()
+{
+ const vec& macros = MacroList::instance()->macros();
+ for ( vec::const_reverse_iterator i = macros.rbegin(); i != macros.rend(); ++i )
+ {
+ typeList->insertItem( newListItem( *i ) );
+ }
+}
+
+void TypesDialog::cancelSlot()
+{
+ mpart.deleteTypes();
+ mpart.loadTypes();
+ reject();
+}
diff --git a/kig/modes/typesdialog.h b/kig/modes/typesdialog.h
new file mode 100644
index 00000000..6f0e4702
--- /dev/null
+++ b/kig/modes/typesdialog.h
@@ -0,0 +1,70 @@
+/*
+ This file is part of Kig, a KDE program for Interactive Geometry...
+ Copyright (C) 2002 Dominique Devriese <devriese@kde.org>
+
+ 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
+*/
+
+#ifndef KIG_MODES_TYPESDIALOG_H
+#define KIG_MODES_TYPESDIALOG_H
+
+#include "typesdialogbase.h"
+
+#include "../misc/lists.h"
+
+#include <qpopupmenu.h>
+
+#include <klistview.h>
+#include <kiconloader.h>
+
+class KigPart;
+class KigDocument;
+
+/**
+ * Manage the macro types...
+ */
+class TypesDialog : public TypesDialogBase
+{
+ Q_OBJECT
+
+ // necessary because some MacroList functions need it..
+ KigPart& mpart;
+ const KIconLoader* il;
+ QPopupMenu* popup;
+public:
+ TypesDialog( QWidget* parent, KigPart& );
+ ~TypesDialog();
+
+public slots:
+ void helpSlot();
+ void okSlot();
+ void cancelSlot();
+
+protected slots:
+ void deleteType();
+ void exportType();
+ void importTypes();
+ void editType();
+ void contextMenuRequested( QListViewItem* i, const QPoint& p, int c );
+
+private:
+ QListViewItem* newListItem( Macro* m );
+ QString fetchIconFromListItem( QListViewItem* i );
+ void loadAllMacros();
+ typedef MacroList::vectype vec;
+};
+
+#endif
diff --git a/kig/modes/typesdialogbase.ui b/kig/modes/typesdialogbase.ui
new file mode 100644
index 00000000..7cc7effb
--- /dev/null
+++ b/kig/modes/typesdialogbase.ui
@@ -0,0 +1,337 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>TypesDialogBase</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>TypesDialogBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>456</width>
+ <height>249</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Manage Types</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can manage types; you can remove them, and load and save them from and to files...</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KListView">
+ <column>
+ <property name="text">
+ <string>Icon</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Description</string>
+ </property>
+ <property name="clickable">
+ <bool>false</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>typeList</cstring>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>Extended</enum>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select types here...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is a list of the current macro types... You can select, edit, delete, export and import them...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonEdit</cstring>
+ </property>
+ <property name="text">
+ <string>Edit...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Edit the selected type.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonRemove</cstring>
+ </property>
+ <property name="text">
+ <string>Delete</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Delete all the selected types in the list.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonExport</cstring>
+ </property>
+ <property name="text">
+ <string>Export...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Export all the selected types to a file.</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonImport</cstring>
+ </property>
+ <property name="text">
+ <string>Import...</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Import macros that are contained in one or more files.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>buttonExport</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>exportType()</slot>
+ </connection>
+ <connection>
+ <sender>buttonHelp</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>helpSlot()</slot>
+ </connection>
+ <connection>
+ <sender>buttonImport</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>importTypes()</slot>
+ </connection>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>okSlot()</slot>
+ </connection>
+ <connection>
+ <sender>buttonRemove</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>deleteType()</slot>
+ </connection>
+ <connection>
+ <sender>buttonEdit</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>editType()</slot>
+ </connection>
+ <connection>
+ <sender>typeList</sender>
+ <signal>contextMenuRequested(QListViewItem*,const QPoint&amp;,int)</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>contextMenuRequested(QListViewItem*,const QPoint&amp;,int)</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>TypesDialogBase</receiver>
+ <slot>cancelSlot()</slot>
+ </connection>
+</connections>
+<slots>
+ <slot access="protected">deleteType()</slot>
+ <slot access="protected">exportType()</slot>
+ <slot>helpSlot()</slot>
+ <slot access="protected">importTypes()</slot>
+ <slot>okSlot()</slot>
+ <slot access="protected">editType()</slot>
+ <slot access="protected">contextMenuRequested( QListViewItem* i, const QPoint&amp; p, int c )</slot>
+ <slot>cancelSlot()</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>klistview.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+</includehints>
+</UI>