1 /* 2 SPDX-FileCopyrightText: 2002-2007 Hamish Rodda <rodda@kde.org> 3 SPDX-FileCopyrightText: 2002 John Firebaugh <jfirebaugh@kde.org> 4 SPDX-FileCopyrightText: 2002 Joseph Wenninger <jowenn@kde.org> 5 SPDX-FileCopyrightText: 2002 Christoph Cullmann <cullmann@kde.org> 6 SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch> 7 8 Based on KWriteView: 9 SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> 10 11 SPDX-License-Identifier: LGPL-2.0-or-later 12 */ 13 #ifndef _KATE_VIEW_INTERNAL_ 14 #define _KATE_VIEW_INTERNAL_ 15 16 #include <ktexteditor/attribute.h> 17 #include <ktexteditor/view.h> 18 19 #include "inlinenotedata.h" 20 #include "katetextcursor.h" 21 #include "katetextline.h" 22 23 #include <QDrag> 24 #include <QElapsedTimer> 25 #include <QPoint> 26 #include <QPointer> 27 #include <QSet> 28 #include <QTime> 29 #include <QTimer> 30 #include <QWidget> 31 32 #include <array> 33 #include <memory> 34 35 namespace KTextEditor 36 { 37 class MovingRange; 38 class TextHintProvider; 39 class DocumentPrivate; 40 class ViewPrivate; 41 } 42 43 class KateIconBorder; 44 class KateScrollBar; 45 class KateAnnotationItemDelegate; 46 class KateAnnotationGroupPositionState; 47 class KateTextLayout; 48 class KateTextAnimation; 49 class KateAbstractInputMode; 50 class ZoomEventFilter; 51 class KateRenderer; 52 class KateTextPreview; 53 class KateViewTest; 54 55 class QScrollBar; 56 class QScroller; 57 class QScrollEvent; 58 class QScrollPrepareEvent; 59 60 class KTEXTEDITOR_EXPORT KateViewInternal : public QWidget 61 { 62 Q_OBJECT 63 64 friend class KTextEditor::ViewPrivate; 65 friend class KateIconBorder; 66 friend class KateScrollBar; 67 friend class KateAnnotationGroupPositionState; 68 friend class CalculatingCursor; 69 friend class BoundedCursor; 70 friend class WrappingCursor; 71 friend class CamelCursor; 72 friend class KateAbstractInputMode; 73 friend class ::KateTextPreview; 74 friend class KateViewTest; 75 76 public: 77 enum Bias { left = -1, none = 0, right = 1 }; 78 79 public: 80 explicit KateViewInternal(KTextEditor::ViewPrivate *view); 81 ~KateViewInternal() override; view()82 KTextEditor::ViewPrivate *view() const 83 { 84 return m_view; 85 } 86 87 // BEGIN EDIT STUFF 88 public: 89 void editStart(); 90 void editEnd(int editTagLineStart, int editTagLineEnd, bool tagFrom); 91 92 void editSetCursor(const KTextEditor::Cursor cursor); 93 94 private: 95 uint editSessionNumber; 96 bool editIsRunning; 97 KTextEditor::Cursor editOldCursor; 98 KTextEditor::Range editOldSelection; 99 // END 100 101 // BEGIN TAG & CLEAR & UPDATE STUFF 102 public: 103 bool tagLine(const KTextEditor::Cursor virtualCursor); 104 105 bool tagLines(int start, int end, bool realLines = false); 106 // cursors not const references as they are manipulated within 107 bool tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end, bool realCursors = false); 108 109 bool tagRange(const KTextEditor::Range &range, bool realCursors); 110 111 void tagAll(); 112 113 void updateDirty(); 114 115 void clear(); 116 // END 117 118 private Q_SLOTS: 119 // Updates the view and requests a redraw. 120 void updateView(bool changed = false, int viewLinesScrolled = 0); 121 122 private: 123 void makeVisible(const KTextEditor::Cursor c, int endCol, bool force = false, bool center = false, bool calledExternally = false); 124 125 public: 126 // Start Position is a virtual cursor startPos()127 KTextEditor::Cursor startPos() const 128 { 129 return m_startPos; 130 } startLine()131 int startLine() const 132 { 133 return m_startPos.line(); 134 } startX()135 int startX() const 136 { 137 return m_startX; 138 } 139 140 KTextEditor::Cursor endPos() const; 141 int endLine() const; 142 143 KateTextLayout yToKateTextLayout(int y) const; 144 145 void prepareForDynWrapChange(); 146 void dynWrapChanged(); 147 148 public Q_SLOTS: 149 void slotIncFontSizes(qreal step = 1.0); 150 void slotDecFontSizes(qreal step = 1.0); 151 void slotResetFontSizes(); 152 153 void paintCursor(); 154 155 private Q_SLOTS: 156 void scrollLines(int line); // connected to the sliderMoved of the m_lineScroll 157 void scrollViewLines(int offset); 158 void scrollAction(int action); 159 void scrollNextPage(); 160 void scrollPrevPage(); 161 void scrollPrevLine(); 162 void scrollNextLine(); 163 void scrollColumns(int x); // connected to the valueChanged of the m_columnScroll 164 void viewSelectionChanged(); 165 166 public: 167 void cursorPrevChar(bool sel = false); 168 void cursorNextChar(bool sel = false); 169 void wordPrev(bool sel = false); 170 void wordNext(bool sel = false); 171 void home(bool sel = false); 172 void end(bool sel = false); 173 void cursorUp(bool sel = false); 174 void cursorDown(bool sel = false); 175 void cursorToMatchingBracket(bool sel = false); 176 void scrollUp(); 177 void scrollDown(); 178 void topOfView(bool sel = false); 179 void bottomOfView(bool sel = false); 180 void pageUp(bool sel = false, bool half = false); 181 void pageDown(bool sel = false, bool half = false); 182 void top(bool sel = false); 183 void bottom(bool sel = false); 184 void top_home(bool sel = false); 185 void bottom_end(bool sel = false); 186 187 /** 188 * Accessor to the current caret position 189 * @return position of the caret as @c KTextEditor::Cursor 190 * @see KTextEditor::Cursor 191 */ cursorPosition()192 KTextEditor::Cursor cursorPosition() const 193 { 194 return m_cursor; 195 } 196 197 /** 198 * Accessor to the current mouse position 199 * @return position of the mouse as @c KTextEditor::Cursor 200 * @see KTextEditor::Cursor 201 */ mousePosition()202 KTextEditor::Cursor mousePosition() const 203 { 204 return m_mouse; 205 } 206 207 QPoint cursorToCoordinate(const KTextEditor::Cursor cursor, bool realCursor = true, bool includeBorder = true) const; 208 // by default, works on coordinates of the whole widget, eg. offsetted by the border 209 KTextEditor::Cursor coordinatesToCursor(const QPoint &coord, bool includeBorder = true) const; 210 QPoint cursorCoordinates(bool includeBorder = true) const; 211 KTextEditor::Cursor findMatchingBracket(); 212 213 KTextEditor::Range findMatchingFoldingMarker(const KTextEditor::Cursor current_cursor_pos, const int value, const int maxLines); 214 void updateFoldingMarkersHighlighting(); 215 getStartOffset(int direction,int offset,int length)216 inline int getStartOffset(int direction, int offset, int length) const 217 { 218 return direction == 1 ? offset - length : offset; 219 } 220 getEndOffset(int direction,int offset,int length)221 inline int getEndOffset(int direction, int offset, int length) const 222 { 223 return direction == 1 ? offset : offset + length; 224 } 225 iconBorder()226 KateIconBorder *iconBorder() const 227 { 228 return m_leftBorder; 229 } 230 231 bool isUserSelecting() const; 232 233 // EVENT HANDLING STUFF - IMPORTANT 234 private: 235 void fixDropEvent(QDropEvent *event); 236 237 bool isAcceptableInput(const QKeyEvent *e) const; 238 239 protected: 240 void hideEvent(QHideEvent *e) override; 241 void paintEvent(QPaintEvent *e) override; 242 bool eventFilter(QObject *obj, QEvent *e) override; 243 void keyPressEvent(QKeyEvent *) override; 244 void keyReleaseEvent(QKeyEvent *) override; 245 void resizeEvent(QResizeEvent *) override; 246 void moveEvent(QMoveEvent *) override; 247 void mousePressEvent(QMouseEvent *) override; 248 void mouseDoubleClickEvent(QMouseEvent *) override; 249 void mouseReleaseEvent(QMouseEvent *) override; 250 void mouseMoveEvent(QMouseEvent *) override; 251 void leaveEvent(QEvent *) override; 252 void dragEnterEvent(QDragEnterEvent *) override; 253 void dragMoveEvent(QDragMoveEvent *) override; 254 void dropEvent(QDropEvent *) override; 255 void showEvent(QShowEvent *) override; 256 void wheelEvent(QWheelEvent *e) override; 257 void scrollPrepareEvent(QScrollPrepareEvent *); 258 void scrollEvent(QScrollEvent *); 259 void focusInEvent(QFocusEvent *) override; 260 void focusOutEvent(QFocusEvent *) override; 261 void inputMethodEvent(QInputMethodEvent *e) override; 262 263 void contextMenuEvent(QContextMenuEvent *e) override; 264 265 private Q_SLOTS: 266 void tripleClickTimeout(); 267 268 Q_SIGNALS: 269 // emitted when KateViewInternal is not handling its own URI drops 270 void dropEventPass(QDropEvent *); 271 272 private Q_SLOTS: 273 void slotRegionVisibilityChanged(); 274 void slotRegionBeginEndAddedRemoved(unsigned int); 275 276 private: 277 void moveChar(Bias bias, bool sel); 278 void moveEdge(Bias bias, bool sel); 279 KTextEditor::Cursor maxStartPos(bool changed = false); 280 void scrollPos(KTextEditor::Cursor &c, bool force = false, bool calledExternally = false, bool emitSignals = true); 281 void scrollLines(int lines, bool sel); 282 283 KTextEditor::Attribute::Ptr attributeAt(const KTextEditor::Cursor position) const; 284 int linesDisplayed() const; 285 286 int lineToY(int viewLine) const; 287 288 void updateSelection(const KTextEditor::Cursor, bool keepSel); 289 void setSelection(const KTextEditor::Range &); 290 void moveCursorToSelectionEdge(); 291 void updateCursor(const KTextEditor::Cursor newCursor, bool force = false, bool center = false, bool calledExternally = false); 292 void updateBracketMarks(); 293 void beginSelectLine(const QPoint &pos); 294 295 void placeCursor(const QPoint &p, bool keepSelection = false, bool updateSelection = true); 296 bool isTargetSelected(const QPoint &p); 297 // Returns whether the given range affects the area currently visible in the view 298 bool rangeAffectsView(const KTextEditor::Range &range, bool realCursors) const; 299 300 void doDrag(); 301 302 KateRenderer *renderer() const; 303 304 KTextEditor::ViewPrivate *m_view; 305 class KateIconBorder *m_leftBorder; 306 307 int m_mouseX; 308 int m_mouseY; 309 int m_scrollX; 310 int m_scrollY; 311 312 std::unique_ptr<ZoomEventFilter> m_zoomEventFilter; 313 314 Qt::CursorShape m_mouseCursor; 315 316 Kate::TextCursor m_cursor; 317 KTextEditor::Cursor m_mouse; 318 KTextEditor::Cursor m_displayCursor; 319 320 bool m_possibleTripleClick; 321 322 // Whether the current completion-item was expanded while the last press of ALT 323 bool m_completionItemExpanded; 324 QElapsedTimer m_altDownTime; 325 326 // Bracket mark and corresponding decorative ranges 327 std::unique_ptr<KTextEditor::MovingRange> m_bm, m_bmStart, m_bmEnd; 328 std::unique_ptr<KTextEditor::MovingCursor> m_bmLastFlashPos; 329 std::unique_ptr<KateTextPreview> m_bmPreview; 330 void updateBracketMarkAttributes(); 331 332 // Folding mark 333 std::unique_ptr<KTextEditor::MovingRange> m_fmStart, m_fmEnd; 334 335 enum DragState { diNone, diPending, diDragging }; 336 337 struct _dragInfo { 338 DragState state; 339 QPoint start; 340 QDrag *dragObject; 341 } m_dragInfo; 342 343 // 344 // line scrollbar + first visible (virtual) line in the current view 345 // 346 KateScrollBar *m_lineScroll; 347 qreal m_accumulatedScroll = 0.0; 348 QWidget *m_dummy; 349 350 // These are now cursors to account for word-wrap. 351 // Start Position is a virtual cursor 352 Kate::TextCursor m_startPos; 353 // Count of lines that are visible behind m_startPos. 354 // This does not respect dynamic word wrap, so take it as an approximation. 355 uint m_visibleLineCount; 356 357 // This is set to false on resize or scroll (other than that called by makeVisible), 358 // so that makeVisible is again called when a key is pressed and the cursor is in the same spot 359 bool m_madeVisible; 360 bool m_shiftKeyPressed; 361 362 // How many lines to should be kept visible above/below the cursor when possible 363 void setAutoCenterLines(int viewLines, bool updateView = true); 364 int m_autoCenterLines; 365 int m_minLinesVisible; 366 367 // 368 // column scrollbar + x position 369 // 370 QScrollBar *m_columnScroll; 371 QScroller *m_scroller; 372 int m_startX; 373 374 // has selection changed while your mouse or shift key is pressed 375 bool m_selChangedByUser; 376 KTextEditor::Cursor m_selectAnchor; 377 378 enum SelectionMode { Default = 0, Mouse, Word, Line }; ///< for drag selection. 379 uint m_selectionMode; 380 // when drag selecting after double/triple click, keep the initial selected 381 // word/line independent of direction. 382 // They get set in the event of a double click, and is used with mouse move + leftbutton 383 KTextEditor::Range m_selectionCached; 384 385 // maximal length of textlines visible from given startLine 386 int maxLen(int startLine); 387 388 // are we allowed to scroll columns? 389 bool columnScrollingPossible(); 390 391 // the same for lines 392 bool lineScrollingPossible(); 393 394 // returns the maximum X value / col value a cursor can take for a specific line range 395 int lineMaxCursorX(const KateTextLayout &line); 396 int lineMaxCol(const KateTextLayout &line); 397 398 class KateLayoutCache *cache() const; 399 KateLayoutCache *m_layoutCache; 400 401 // convenience methods 402 KateTextLayout currentLayout() const; 403 KateTextLayout previousLayout() const; 404 KateTextLayout nextLayout() const; 405 406 // find the cursor offset by (offset) view lines from a cursor. 407 // when keepX is true, the column position will be calculated based on the x 408 // position of the specified cursor. 409 KTextEditor::Cursor viewLineOffset(const KTextEditor::Cursor virtualCursor, int offset, bool keepX = false); 410 411 KTextEditor::Cursor toRealCursor(const KTextEditor::Cursor virtualCursor) const; 412 KTextEditor::Cursor toVirtualCursor(const KTextEditor::Cursor realCursor) const; 413 414 // These variable holds the most recent maximum real & visible column number 415 bool m_preserveX; 416 int m_preservedX; 417 418 int m_wrapChangeViewLine; 419 KTextEditor::Cursor m_cachedMaxStartPos; 420 421 // 422 // implementation details for KTextEditor::FlashTextInterface 423 // 424 public: 425 void flashChar(const KTextEditor::Cursor pos, KTextEditor::Attribute::Ptr attribute); 426 void showBracketMatchPreview(); 427 void hideBracketMatchPreview(); 428 429 private: 430 QPointer<KateTextAnimation> m_textAnimation; 431 432 private Q_SLOTS: 433 void doDragScroll(); 434 void startDragScroll(); 435 void stopDragScroll(); 436 437 private: 438 // Timers 439 QTimer m_dragScrollTimer; 440 QTimer m_scrollTimer; 441 QTimer m_cursorTimer; 442 QTimer m_textHintTimer; 443 444 static const int s_scrollTime = 30; 445 static const int s_scrollMargin = 16; 446 447 private Q_SLOTS: 448 void scrollTimeout(); 449 void cursorTimeout(); 450 void textHintTimeout(); 451 452 void documentTextInserted(KTextEditor::Document *document, const KTextEditor::Range &range); 453 void documentTextRemoved(KTextEditor::Document *document, const KTextEditor::Range &range, const QString &oldText); 454 455 // 456 // KTE::TextHintInterface 457 // 458 public: 459 void registerTextHintProvider(KTextEditor::TextHintProvider *provider); 460 void unregisterTextHintProvider(KTextEditor::TextHintProvider *provider); 461 void setTextHintDelay(int delay); 462 int textHintDelay() const; 463 bool textHintsEnabled(); // not part of the interface 464 465 private: 466 std::vector<KTextEditor::TextHintProvider *> m_textHintProviders; 467 int m_textHintDelay; 468 QPoint m_textHintPos; 469 470 // 471 // IM input stuff 472 // 473 public: 474 QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; 475 476 private: 477 std::unique_ptr<KTextEditor::MovingRange> m_imPreeditRange; 478 std::vector<std::unique_ptr<KTextEditor::MovingRange>> m_imPreeditRangeChildren; 479 480 private: 481 void mouseMoved(); 482 void cursorMoved(); 483 484 private: 485 KTextEditor::DocumentPrivate *doc(); 486 KTextEditor::DocumentPrivate *doc() const; 487 488 // input modes 489 private: 490 std::array<std::unique_ptr<KateAbstractInputMode>, KTextEditor::View::ViInputMode + 1> m_inputModes; 491 KateAbstractInputMode *m_currentInputMode; 492 493 KateInlineNoteData m_activeInlineNote; 494 KateInlineNoteData inlineNoteAt(const QPoint &globalPos) const; 495 QRect inlineNoteRect(const KateInlineNoteData ¬e) const; 496 }; 497 498 #endif 499