00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "KWFrameView.h"
00019 #include "KWFrameViewManager.h"
00020 #include "KWFrame.h"
00021 #include "KWFrameSet.h"
00022 #include "KWTextFrameSet.h"
00023 #include "KWTableFrameSet.h"
00024 #include "KWPartFrameSet.h"
00025 #include "KWVariable.h"
00026 #include "KWPictureFrameSet.h"
00027 #include "KWViewMode.h"
00028 #include "KWDocument.h"
00029 #include "KWCanvas.h"
00030
00031 #include "KoZoomHandler.h"
00032
00033 #include <klocale.h>
00034 #include <kactionclasses.h>
00035
00036 #include <qapplication.h>
00037 #include <qpopupmenu.h>
00038
00039 static const double HORIZONTAL_SNAP = 6;
00040 static const double VERTICAL_SNAP = 6;
00041
00042 KWFrameView::KWFrameView(KWFrameViewManager *parent, KWFrame *frame) {
00043 m_manager = parent;
00044 Q_ASSERT(frame);
00045 Q_ASSERT(frame->frameSet());
00046 m_frame = frame;
00047 m_selected = false;
00048 if(frame->frameSet()->groupmanager() || dynamic_cast<KWTableFrameSet *>(frame->frameSet()) != 0)
00049 m_policy = new TableFramePolicy(this);
00050 else if(dynamic_cast<KWTextFrameSet *>(frame->frameSet()) != 0)
00051 m_policy = new TextFramePolicy(this);
00052 else if(dynamic_cast<KWPartFrameSet *>(frame->frameSet()) != 0)
00053 m_policy = new PartFramePolicy(this);
00054 else if(dynamic_cast<KWPictureFrameSet *>(frame->frameSet()) != 0)
00055 m_policy = new ImageFramePolicy(this);
00056 else {
00057 m_policy = new TextFramePolicy(this);
00058 kdWarning() << "Unknown frameset supplied!" << endl;
00059 }
00060 }
00061
00062 KWFrameView::~KWFrameView() {
00063 delete m_policy;
00064 }
00065
00066 bool KWFrameView::isBorderHit(const KoPoint &point) const {
00067 return hit(point, true, true);
00068 }
00069
00070 bool KWFrameView::contains(const KoPoint &point, bool fuzzy) const {
00071 return hit(point, fuzzy, false);
00072 }
00073
00074 bool KWFrameView::hit(const KoPoint &point, bool fuzzy , bool borderOnly) const {
00075
00076 double hs = 0, vs =0;
00077 if(fuzzy) {
00078 hs = HORIZONTAL_SNAP;
00079 if(frame()->width() < HORIZONTAL_SNAP * 3)
00080 hs = frame()->width() / 3;
00081 vs = VERTICAL_SNAP;
00082 if(frame()->height() < VERTICAL_SNAP * 3)
00083 vs = frame()->height() / 3;
00084 }
00085 if(point.x() < frame()->x() - hs)
00086 return false;
00087 if(point.x() > frame()->right() + hs)
00088 return false;
00089 if(point.y() < frame()->y() - vs)
00090 return false;
00091 if(point.y() > frame()->bottom() + vs)
00092 return false;
00093
00094 if(borderOnly) {
00095 if(point.x() > frame()->x() + hs && point.x() < frame()->right() - hs &&
00096 point.y() > frame()->y() + vs && point.y() < frame()->bottom() - vs )
00097 return false;
00098 }
00099 return true;
00100 }
00101
00102 MouseMeaning KWFrameView::mouseMeaning( const KoPoint &point, int keyState ) {
00103 if(isBorderHit(point)) {
00104 MouseMeaning mm = m_policy->mouseMeaningOnBorder(point, keyState);
00105 if(mm != MEANING_NONE && ( frame()->frameSet()->isProtectSize() ||
00106 frame()->frameSet()->isMainFrameset() || frame()->frameSet()->isAHeader() ||
00107 frame()->frameSet()->isAFooter() ))
00108 mm = MEANING_FORBIDDEN;
00109 return mm;
00110 }
00111 if(hit(point, false, false))
00112 return m_policy->mouseMeaning(point, keyState);
00113 return MEANING_NONE;
00114 }
00115
00116 void KWFrameView::setSelected(bool selected, MouseMeaning selectPolicy) {
00117 m_policy->setSelected(selectPolicy);
00118 if( m_selected == selected ) return;
00119 m_manager->slotFrameSelectionChanged();
00120 m_selected = selected;
00121 }
00122
00123 void KWFrameView::showPopup( const KoPoint &point, KWView *view, const QPoint &popupPoint) const {
00124 view->unplugActionList( "tableactions" );
00125 view->unplugActionList( "frameset_type_action" );
00126 QPopupMenu *popup = m_policy->createPopup(point, view);
00127 Q_ASSERT(popup);
00128 popup->popup(popupPoint);
00129 }
00130
00131 void KWFrameView::paintFrameAttributes(QPainter *painter, const QRect &crect, KWViewMode *vm, KoZoomHandler *zh) {
00132 if( !m_selected )
00133 return;
00134
00135 class ResizeHandle {
00136 private:
00137 const int GRIP_SIZE;
00138 bool readOnly;
00139 public:
00140 ResizeHandle(KWFrameView *fv) : GRIP_SIZE(6) {
00141 KWFrameSet *fs = fv->frame()->frameSet();
00142 readOnly = fs->isProtectSize() || fs->isMainFrameset() ||
00143 fs->isAHeader() || fs->isAFooter() || fs->isFloating();
00144 }
00145 void paint(QPainter *p, int x, int y) {
00146 p->setPen( QPen( Qt::black, 1, QPen::SolidLine ) );
00147 p->setBrush( QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ) );
00148 p->drawRect( x, y, GRIP_SIZE, GRIP_SIZE );
00149 if( readOnly ) {
00150 QBrush brush = QApplication::palette().color( QPalette::Active,QColorGroup::Base );
00151 p->fillRect( x+1, y+1, GRIP_SIZE-2, GRIP_SIZE-2, brush );
00152 }
00153 }
00154 };
00155
00156 const QRect frameRect = vm->normalToView( zh->zoomRect( *frame() ) );
00157 if ( crect.intersects( frameRect ) )
00158 {
00159 ResizeHandle handle(this);
00160
00161 const int width = frameRect.width();
00162 const int height = frameRect.height();
00163 for(int y=0; y < 3; y++) {
00164 int offsetY = -1 + y + frameRect.y();
00165 if(y > 0) offsetY += (height - 6) / (y == 1 ? 2:1);
00166 for(int x=0; x < 3; x++) {
00167 if(x == 1 && y == 1) continue;
00168 int offsetX = -1 + x + frameRect.x();
00169 if(x > 0) offsetX += (width - 6) / (x == 1 ? 2:1);
00170 handle.paint(painter, offsetX, offsetY);
00171 }
00172 }
00173 }
00174 }
00175
00176
00177 FramePolicy::FramePolicy(KWFrameView *view) {
00178 m_separator = new KActionSeparator();
00179 m_view = view;
00180 }
00181 void FramePolicy::addFloatingAction(KWView *view, QPtrList<KAction> &actionList) {
00182 if(m_view->frame()->frameSet()->isMainFrameset())
00183 return;
00184 actionList.append(m_separator);
00185 KToggleAction *action = dynamic_cast<KToggleAction*> (view->actionCollection()->
00186 action("inline_frame"));
00187 Q_ASSERT(action);
00188 KWFrameSet *parentFs = m_view->frame()->frameSet()->groupmanager() ?
00189 m_view->frame()->frameSet()->groupmanager() : m_view->frame()->frameSet();
00190 action->setChecked(parentFs->isFloating());
00191 actionList.append(action);
00192 }
00193 MouseMeaning FramePolicy::mouseMeaningOnBorder( const KoPoint &point, int keyState ) {
00194 Q_UNUSED(keyState);
00195 double hs = HORIZONTAL_SNAP;
00196 KWFrame *frame = m_view->frame();
00197 if(frame->width() < HORIZONTAL_SNAP * 3)
00198 hs = frame->width() / 3;
00199 double vs = VERTICAL_SNAP;
00200 if(frame->height() < VERTICAL_SNAP * 3)
00201 vs = frame->height() / 3;
00202
00203
00204 if( point.x() <= frame->x() + hs ) {
00205 if(point.y() <= frame->y() + vs)
00206 return MEANING_TOPLEFT;
00207 if(point.y() >= frame->bottom() - vs)
00208 return MEANING_BOTTOMLEFT;
00209 if( QABS(frame->y() + frame->height() / 2 - point.y()) <= vs )
00210 return MEANING_LEFT;
00211 return MEANING_MOUSE_MOVE;
00212 }
00213 if( point.x() >= frame->right() - hs) {
00214 if(point.y() <= frame->y() + vs)
00215 return MEANING_TOPRIGHT;
00216 if(point.y() >= frame->bottom() - vs)
00217 return MEANING_BOTTOMRIGHT;
00218 if( QABS(frame->y() + frame->height() / 2 - point.y()) <= vs )
00219 return MEANING_RIGHT;
00220 return MEANING_MOUSE_MOVE;
00221 }
00222
00223 if( frame->y() + vs >= point.y() ) {
00224 if( QABS(frame->x() + frame->width() / 2 - point.x() ) <= hs )
00225 return MEANING_TOP;
00226 return MEANING_MOUSE_MOVE;
00227 }
00228 if( frame->bottom() - vs <= point.y() ) {
00229 if( QABS(frame->x() + frame->width() / 2 - point.x() ) <= hs )
00230 return MEANING_BOTTOM;
00231 return MEANING_MOUSE_MOVE;
00232 }
00233 return MEANING_NONE;
00234 }
00235
00236 TableFramePolicy::TableFramePolicy(KWFrameView *view) : FramePolicy (view) {
00237 }
00238 MouseMeaning TableFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
00239 Q_UNUSED(point);
00240
00241
00242 if ( keyState & Qt::ControlButton )
00243 return MEANING_MOUSE_SELECT;
00244
00245
00246 if ( (keyState & Qt::ShiftButton) && m_view->parent()->selectedFrame() != 0 )
00247 return MEANING_MOUSE_SELECT;
00248
00249 return MEANING_MOUSE_INSIDE_TEXT;
00250 }
00251 QPopupMenu* TableFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
00252 view->plugActionList( "tableactions", view->tableActions() );
00253 if( m_view->isBorderHit(point) )
00254 return view->popupMenu("frame_popup_table");
00255 return view->popupMenu("text_popup");
00256 }
00257 MouseMeaning TableFramePolicy::mouseMeaningOnBorder(const KoPoint &point, int keyState) {
00258 KWFrame *frame = m_view->frame();
00259 double hs = HORIZONTAL_SNAP;
00260 double vs = VERTICAL_SNAP;
00261 bool ctrl = keyState & Qt::ControlButton;
00262
00263 if ( QABS( frame->x() - point.x() ) < hs
00264 && point.y() >= frame->y() && point.y() <= frame->bottom() ) {
00265 if( static_cast<KWTableFrameSet::Cell *>(frame->frameSet())->firstColumn() == 0 )
00266 return MEANING_SELECT_ROW;
00267 if(!ctrl)
00268 return MEANING_RESIZE_COLUMN;
00269 }
00270 if ( QABS( frame->y() - point.y() ) < vs
00271 && point.x() >= frame->x() && point.x() <= frame->right() ) {
00272 if( static_cast<KWTableFrameSet::Cell *>(frame->frameSet())->firstRow() == 0 )
00273 return MEANING_SELECT_COLUMN;
00274 if(!ctrl)
00275 return MEANING_MOUSE_SELECT;
00276 }
00277
00278 if (ctrl)
00279 return MEANING_MOUSE_SELECT;
00280 if ( QABS( frame->right() - point.x() ) < hs
00281 && point.y() >= frame->y() && point.y() <= frame->bottom() )
00282 return MEANING_RESIZE_COLUMN;
00283 if ( QABS( frame->bottom() - point.y() ) < vs
00284 && point.x() >= frame->x() && point.x() <= frame->right() )
00285 return MEANING_MOUSE_SELECT;
00286 return MEANING_NONE;
00287 }
00288 void TableFramePolicy::setSelected(MouseMeaning selectPolicy) {
00289 KWFrameSet *fs = m_view->frame()->frameSet();
00290 if( selectPolicy == MEANING_SELECT_COLUMN ) {
00291 unsigned int column = static_cast<KWTableFrameSet::Cell *>(fs)->firstColumn();
00292 for (KWTableFrameSet::TableIter cells(fs->groupmanager()); cells; ++cells) {
00293 if(cells->firstColumn() >= column && cells->lastColumn() <= column) {
00294 KWFrameView *fv = m_view->parent()->view(cells->frame(0));
00295 if(fv)
00296 fv->setSelected(true);
00297 }
00298 }
00299 }
00300 else if( selectPolicy == MEANING_SELECT_ROW ) {
00301 unsigned int row = static_cast<KWTableFrameSet::Cell *>(fs)->firstRow();
00302 for (KWTableFrameSet::TableIter cells(fs->groupmanager()); cells; ++cells) {
00303 if(cells->firstRow() >= row && cells->lastRow() <= row) {
00304 KWFrameView *fv = m_view->parent()->view(cells->frame(0));
00305 if(fv)
00306 fv->setSelected(true);
00307 }
00308 }
00309 }
00310 else if( selectPolicy == MEANING_SELECT_RANGE ) {
00311 kdDebug() << "not yet implemented; select table range\n";
00312 }
00313 }
00314
00315 PartFramePolicy::PartFramePolicy(KWFrameView *view) : FramePolicy (view) {
00316 }
00317 MouseMeaning PartFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
00318 Q_UNUSED(point);
00319
00320 if( keyState & Qt::ControlButton ) {
00321 return m_view->selected() ? MEANING_MOUSE_MOVE : MEANING_MOUSE_SELECT;
00322 }
00323 if ( m_view->selected() )
00324 return MEANING_ACTIVATE_PART;
00325 return MEANING_MOUSE_SELECT;
00326 }
00327 QPopupMenu* PartFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
00328 Q_UNUSED(point);
00329 KWPartFrameSet *part = static_cast<KWPartFrameSet *>(m_view->frame()->frameSet());
00330 KActionSeparator *separator=new KActionSeparator();
00331 KActionCollection *actionCollection = view->actionCollection();
00332 QPtrList<KAction> actionList;
00333 actionList.append(separator);
00334 if( !part->protectContent() ) {
00335 KToggleAction *action = dynamic_cast<KToggleAction*>(actionCollection->action("embedded_store_internal"));
00336 Q_ASSERT(action);
00337 action->setChecked(part->getChild()->document()->storeInternal());
00338 action->setEnabled(part->getChild()->document()->hasExternURL());
00339 actionList.append(action);
00340 }
00341 addFloatingAction(view, actionList);
00342 view->plugActionList( "frameset_type_action", actionList );
00343
00344 return view->popupMenu("frame_popup");
00345 }
00346
00347 TextFramePolicy::TextFramePolicy(KWFrameView *view) : FramePolicy (view) {
00348 }
00349 MouseMeaning TextFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
00350 if( (keyState & Qt::ControlButton) == Qt::ControlButton )
00351 return MEANING_MOUSE_SELECT;
00352 KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet*>(m_view->frame()->frameSet());
00353 if(fs == 0 || fs->kWordDocument() == 0)
00354 return MEANING_MOUSE_INSIDE_TEXT;
00355 KWVariableCollection *varCol = fs->kWordDocument()->variableCollection();
00356 if (varCol->variableSetting()->displayLink() && varCol->variableSetting()->underlineLink()
00357 && fs->linkVariableUnderMouse( point ) )
00358 return MEANING_MOUSE_OVER_LINK;
00359 KoVariable* var = fs->variableUnderMouse(point);
00360 if ( var ) {
00361 KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
00362 if ( footNoteVar )
00363 return MEANING_MOUSE_OVER_FOOTNOTE;
00364 }
00365 return MEANING_MOUSE_INSIDE_TEXT;
00366 }
00367 QPopupMenu* TextFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
00368 if( m_view->isBorderHit(point) ) {
00369 KWFrameSet *fs = m_view->frame()->frameSet();
00370 KActionSeparator *separator=new KActionSeparator();
00371 KActionCollection *actionCollection = view->actionCollection();
00372 QPtrList<KAction> actionList;
00373 if(fs->isHeaderOrFooter()) {
00374 actionList.append(separator);
00375 actionList.append(actionCollection->action("configure_headerfooter"));
00376 }
00377 else if (fs->isFootEndNote()) {
00378 actionList.append(separator);
00379 KAction *action = actionCollection->action("goto_footendnote");
00380 action->setText( fs->isFootNote() ?
00381 i18n( "Go to Footnote" ) : i18n( "Go to Endnote" ) );
00382 actionList.append(action);
00383 }
00384 addFloatingAction(view, actionList);
00385 view->plugActionList( "frameset_type_action", actionList );
00386 return view->popupMenu("frame_popup");
00387 }
00388
00389 if ( view->getGUI()->canvasWidget()->currentFrameSetEdit()->frameSet()->type() == FT_FORMULA )
00390 return view->popupMenu("Formula");
00391
00392
00393 KWTextFrameSetEdit *fse = static_cast<KWTextFrameSetEdit*> (view->getGUI()->
00394 canvasWidget()->currentFrameSetEdit());
00395
00396 QString word = fse->wordUnderCursor( *fse->cursor() );
00397
00398
00399 view->unplugActionList( "datatools" );
00400 view->unplugActionList( "variable_action" );
00401 view->unplugActionList( "spell_result_action" );
00402 view->unplugActionList( "datatools_link" );
00403
00404
00405 QPtrList<KAction> &actionList = view->dataToolActionList();
00406 QPtrList<KAction> &variableList = view->variableActionList();
00407
00408 actionList.clear();
00409 variableList.clear();
00410
00411 bool singleWord= false;
00412 KWDocument * doc = m_view->frame()->frameSet()->kWordDocument();
00413 actionList = fse->dataToolActionList(doc->instance(), word, singleWord);
00414
00415 KoVariable* var = fse->variable();
00416 doc->variableCollection()->setVariableSelected(var);
00417 if ( var )
00418 variableList = doc->variableCollection()->popupActionList();
00419
00420 if( variableList.count()>0) {
00421 view->plugActionList( "variable_action", variableList );
00422 return view->popupMenu("variable_popup");
00423 }
00424
00425
00426 KoLinkVariable* linkVar = dynamic_cast<KoLinkVariable *>( var );
00427 if ( linkVar ) {
00428 view->plugActionList( "datatools_link", actionList );
00429 return view->popupMenu("text_popup_link");
00430 }
00431 view->plugActionList( "datatools", actionList );
00432 KoNoteVariable * noteVar = dynamic_cast<KoNoteVariable *>( var );
00433 if( noteVar )
00434 return view->popupMenu("comment_popup");
00435
00436 KoCustomVariable * customVar = dynamic_cast<KoCustomVariable *>( var );
00437 if( customVar )
00438 return view->popupMenu("custom_var_popup");
00439
00440 KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
00441 if ( footNoteVar ) {
00442 view->changeFootNoteMenuItem( footNoteVar->noteType() == FootNote );
00443 return view->popupMenu("footnote_popup");
00444 }
00445 if ( singleWord ) {
00446 QPtrList<KAction> actionCheckSpellList = view->listOfResultOfCheckWord( word );
00447 if ( !actionCheckSpellList.isEmpty() ) {
00448 view->plugActionList( "spell_result_action", actionCheckSpellList );
00449 return view->popupMenu("text_popup_spell_with_result");
00450 }
00451 return view->popupMenu("text_popup_spell");
00452 }
00453
00454 return view->popupMenu("text_popup");
00455 }
00456
00457
00458 ImageFramePolicy::ImageFramePolicy(KWFrameView *view) : FramePolicy (view) {
00459 }
00460 MouseMeaning ImageFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
00461 Q_UNUSED(point);
00462 Q_UNUSED(keyState);
00463 return m_view->selected() ? MEANING_MOUSE_MOVE: MEANING_MOUSE_SELECT;
00464 }
00465 QPopupMenu* ImageFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
00466 Q_UNUSED(point);
00467 KActionSeparator *separator=new KActionSeparator();
00468 KActionCollection *actionCollection = view->actionCollection();
00469 QPtrList<KAction> actionList;
00470 actionList.append(separator);
00471 KAction *action = actionCollection->action("change_picture");
00472 Q_ASSERT(action);
00473 actionList.append(action);
00474 action = actionCollection->action("save_picture");
00475 Q_ASSERT(action);
00476 actionList.append(action);
00477 addFloatingAction(view, actionList);
00478 view->plugActionList( "frameset_type_action", actionList );
00479
00480 return view->popupMenu("frame_popup");
00481 }