karbon
vdistributecmd.cc00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <klocale.h>
00022
00023 #include "vdistributecmd.h"
00024 #include "vtransformcmd.h"
00025 #include "vdocument.h"
00026 #include "vselection.h"
00027
00028 VDistributeCmd::VDistributeCmd( VDocument *doc, Distribute distribute )
00029 : VCommand( doc, i18n( "Distribute Objects" ) ), m_distribute( distribute )
00030 {
00031 m_trafoCmds.setAutoDelete( true );
00032 }
00033
00034 VDistributeCmd::~VDistributeCmd()
00035 {
00036 }
00037
00038 void
00039 VDistributeCmd::execute()
00040 {
00041 if( document()->selection()->objects().count() <= 2 )
00042 return;
00043
00044 KoRect bbox;
00045 double extent = 0.0;
00046 double dx, dy;
00047
00048 VObjectList objs = document()->selection()->objects();
00049 VObjectListIterator itr( objs );
00050
00051 QMap<double,VObject*> sortedPos;
00052
00053
00054 for( ; itr.current(); ++itr )
00055 {
00056 bbox = itr.current()->boundingBox();
00057 switch( m_distribute )
00058 {
00059 case DISTRIBUTE_HORIZONTAL_CENTER:
00060 sortedPos[bbox.center().x()] = itr.current();
00061 break;
00062 case DISTRIBUTE_HORIZONTAL_GAP:
00063 case DISTRIBUTE_HORIZONTAL_LEFT:
00064 sortedPos[bbox.left()] = itr.current();
00065 extent += bbox.width();
00066 break;
00067 case DISTRIBUTE_HORIZONTAL_RIGHT:
00068 sortedPos[bbox.right()] = itr.current();
00069 break;
00070 case DISTRIBUTE_VERTICAL_CENTER:
00071 sortedPos[bbox.center().y()] = itr.current();
00072 break;
00073 case DISTRIBUTE_VERTICAL_GAP:
00074 case DISTRIBUTE_VERTICAL_BOTTOM:
00075 sortedPos[bbox.bottom()] = itr.current();
00076 extent += bbox.height();
00077 break;
00078 case DISTRIBUTE_VERTICAL_TOP:
00079 sortedPos[bbox.top()] = itr.current();
00080 break;
00081 }
00082 }
00083
00084 VObject* first = sortedPos.begin().data();
00085 VObject* last = (--sortedPos.end()).data();
00086
00087
00088 double space = getAvailableSpace( first, last, extent );
00089 double pos = 0.0, step = space / double(objs.count() - 1);
00090
00091 VTranslateCmd *trafoCmd = 0L;
00092 QMapIterator<double,VObject*> it = sortedPos.begin(), et = sortedPos.end();
00093
00094 for( ; it != et; ++it )
00095 {
00096 if( it.data() == first || it.data() == last )
00097 continue;
00098
00099 pos += step;
00100
00101 document()->selection()->clear();
00102
00103 bbox = it.data()->boundingBox();
00104
00105 switch( m_distribute )
00106 {
00107 case DISTRIBUTE_HORIZONTAL_CENTER:
00108 dx = first->boundingBox().center().x() + pos - bbox.center().x();
00109 dy = 0.0;
00110 break;
00111 case DISTRIBUTE_HORIZONTAL_GAP:
00112 dx = first->boundingBox().right() + pos + 0.5 * bbox.width() - bbox.center().x();
00113 dy = 0.0;
00114 pos += bbox.width();
00115 break;
00116 case DISTRIBUTE_HORIZONTAL_LEFT:
00117 dx = first->boundingBox().left() + pos - bbox.left();
00118 dy = 0.0;
00119 break;
00120 case DISTRIBUTE_HORIZONTAL_RIGHT:
00121 dx = first->boundingBox().right() + pos - bbox.right();
00122 dy = 0.0;
00123 break;
00124 case DISTRIBUTE_VERTICAL_CENTER:
00125 dx = 0.0;
00126 dy = first->boundingBox().center().y() + pos - bbox.center().y();
00127 break;
00128 case DISTRIBUTE_VERTICAL_GAP:
00129 dx = 0.0;
00130 dy = first->boundingBox().bottom() + pos + 0.5 * bbox.height() - bbox.center().y();
00131 pos += bbox.height();
00132 break;
00133 case DISTRIBUTE_VERTICAL_BOTTOM:
00134 dx = 0.0;
00135 dy = first->boundingBox().bottom() + pos - bbox.bottom();
00136 break;
00137 case DISTRIBUTE_VERTICAL_TOP:
00138 dx = 0.0;
00139 dy = first->boundingBox().top() + pos - bbox.top();
00140 break;
00141 };
00142 document()->selection()->append( it.data() );
00143 trafoCmd = new VTranslateCmd( document(), dx, dy );
00144 m_trafoCmds.append( trafoCmd );
00145 trafoCmd->execute();
00146 }
00147
00148
00149 itr.toFirst();
00150 for( ; itr.current() ; ++itr )
00151 document()->selection()->append( itr.current() );
00152 setSuccess( true );
00153 }
00154
00155 void
00156 VDistributeCmd::unexecute()
00157 {
00158 QPtrListIterator<VTranslateCmd> itr( m_trafoCmds );
00159 for( ; itr.current() ; ++itr )
00160 itr.current()->unexecute();
00161 setSuccess( false );
00162 }
00163
00164 double
00165 VDistributeCmd::getAvailableSpace( VObject *first, VObject *last, double extent )
00166 {
00167 switch( m_distribute )
00168 {
00169 case DISTRIBUTE_HORIZONTAL_CENTER:
00170 return last->boundingBox().center().x() - first->boundingBox().center().x();
00171 break;
00172 case DISTRIBUTE_HORIZONTAL_GAP:
00173 extent -= first->boundingBox().width() + last->boundingBox().width();
00174 return last->boundingBox().left() - first->boundingBox().right() - extent;
00175 break;
00176 case DISTRIBUTE_HORIZONTAL_LEFT:
00177 return last->boundingBox().left() - first->boundingBox().left();
00178 break;
00179 case DISTRIBUTE_HORIZONTAL_RIGHT:
00180 return last->boundingBox().right() - first->boundingBox().right();
00181 break;
00182 case DISTRIBUTE_VERTICAL_CENTER:
00183 return last->boundingBox().center().y() - first->boundingBox().center().y();
00184 break;
00185 case DISTRIBUTE_VERTICAL_GAP:
00186 extent -= first->boundingBox().height() + last->boundingBox().height();
00187 return last->boundingBox().top() - first->boundingBox().bottom() - extent;
00188 break;
00189 case DISTRIBUTE_VERTICAL_BOTTOM:
00190 return last->boundingBox().bottom() - first->boundingBox().bottom();
00191 break;
00192 case DISTRIBUTE_VERTICAL_TOP:
00193 return last->boundingBox().top() - first->boundingBox().top();
00194 break;
00195 }
00196
00197 return 0.0;
00198 }
|