1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2009 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #ifndef __SCANVAS_H__
14 #define __SCANVAS_H__
15 
16 #include "globals.h"
17 #include "libmscore/element.h"
18 #include "libmscore/elementgroup.h"
19 #include "libmscore/durationtype.h"
20 #include "libmscore/mscore.h"
21 #include "libmscore/mscoreview.h"
22 #include "libmscore/pos.h"
23 #include "libmscore/harmony.h"
24 #include "mscore/zoombox.h"
25 
26 namespace Ms {
27 
28 class ChordRest;
29 class Rest;
30 class Element;
31 class Page;
32 class XmlWriter;
33 class Note;
34 class Lasso;
35 class FotoLasso;
36 class ShadowNote;
37 class Segment;
38 class Measure;
39 class System;
40 class Score;
41 class ScoreView;
42 class Text;
43 class MeasureBase;
44 class Staff;
45 class OmrView;
46 class PositionCursor;
47 class ContinuousPanel;
48 class Tuplet;
49 class FretDiagram;
50 class Bend;
51 class TremoloBar;
52 class TimeSig;
53 class StaffTextBase;
54 class Articulation;
55 
56 #ifdef Q_OS_MAC
57 #define CONTROL_MODIFIER Qt::AltModifier
58 #else
59 #define CONTROL_MODIFIER Qt::ControlModifier
60 #endif
61 
62 enum class Grip : int;
63 enum class POS : char;
64 enum class ZoomIndex : char;
65 
66 //---------------------------------------------------------
67 //   SmoothPanSettings
68 //---------------------------------------------------------
69 
70 struct SmoothPanSettings {
71       // these are all actually loaded from the loadFromPreferences fuction so don't change these to change the default values,
72       // change the corresponding preferences
73       bool enabled                        { false };
74 
75       double controlModifierBase          { 1 };      // initial speed modifier
76       double controlModifierSteps         { 0.01 };   // modification steps for the modifier
77       double minContinuousModifier        { 0.2 };    // minimum speed, 0.2 was chosen instead of 0 to remove stuttering
78       double maxContinuousModifier        { 5 };      // maximum speed
79 
80       // Changing the distance will change the sensitivity/accuracy/jitter of the algorithm. Larger absolute values are generally smoother.
81       double leftDistance                 { -250 };   // decelarate
82       double leftDistance1                { -125 };
83       double leftDistance2                { -50 };
84       double leftDistance3                { -25 };
85       double rightDistance                { 500 };    // accelerate
86       double rightDistance1               { 250 };
87       double rightDistance2               { 125 };
88       double rightDistance3               { 50 };
89                                                       // used to smoothly go back to normal speed when the playback cursor is getting closer
90       double leftMod1                     { 0.8 };    // minimum speed at the first level
91       double leftMod2                     { 0.9 };    // etc
92       double leftMod3                     { 0.95 };
93                                                       // used to smoothly go back to normal speed when the control cursor is getting closer to the playback cursor
94       double rightMod1                    { 1.2 };    // maximum speed at the first level
95       double rightMod2                    { 1.1 };    // etc
96       double rightMod3                    { 1.05 };
97 
98       double controlCursorScreenPos       { 0.3 };
99       bool teleportLeftEnabled            { true };
100       bool teleportRightEnabled           { false };
101 
102       bool advancedWeighting              { false };  // enables the 'smart weight'
103       double normalWeight                 { 1 };
104       double smartWeight                  { 0 };      // uses the distance between the 2 cursors to calculate the speed of the control cursor
105       int cursorTimerDuration             { 1000 };   // how often the smart weight is updated
106 
107       void loadFromPreferences();
108       };
109 
110 //---------------------------------------------------------
111 //   ViewState
112 //---------------------------------------------------------
113 
114 enum class ViewState {
115       NORMAL,
116       DRAG,
117       DRAG_OBJECT,
118       EDIT,
119       DRAG_EDIT,
120       LASSO,
121       NOTE_ENTRY,
122       PLAY,
123       ENTRY_PLAY,
124 
125       FOTO,
126       FOTO_DRAG,
127       FOTO_DRAG_EDIT,
128       FOTO_DRAG_OBJECT,
129       FOTO_LASSO,
130       };
131 
132 //---------------------------------------------------------
133 //   ScoreViewState
134 //---------------------------------------------------------
135 
136 struct ScoreViewState {
137       qreal logicalZoomLevel = 1.0;
138       ZoomIndex zoomIndex = ZoomIndex::ZOOM_FREE;
139       qreal xOffset = 0.0;
140       qreal yOffset = 0.0;
141 
ScoreViewStateScoreViewState142       ScoreViewState() {}
ScoreViewStateScoreViewState143       ScoreViewState(qreal zl, ZoomIndex zi, qreal x, qreal y)
144             {
145             logicalZoomLevel = zl;
146             zoomIndex = zi;
147             xOffset = x;
148             yOffset = y;
149             }
150 };
151 
152 //---------------------------------------------------------
153 //   ScoreView
154 //---------------------------------------------------------
155 
156 class ScoreView : public QWidget, public MuseScoreView {
157       Q_OBJECT
158 
159       ViewState state;
160       OmrView* _omrView;
161 
162       // the next elements are used during dragMove to give some visual
163       // feedback:
164       //    dropTarget:       if valid, the element is drawn in a different color
165       //                      to mark it as a valid drop target
166       //    dropRectangle:    if valid, the rectangle is filled with a
167       //                      color to visualize a valid drop area
168       //    dropAnchor:       if valid the line is drawn from the current
169       //                      cursor position to the current anchor point
170       // Note:
171       //    only one of the elements is active during drag
172 
173       const Element* dropTarget;    ///< current drop target during dragMove
174       QRectF dropRectangle;         ///< current drop rectangle during dragMove
175       QLineF dropAnchor;            ///< line to current anchor point during dragMove
176       QVector<QLineF> m_dropAnchorLines;
177 
178       QTransform _matrix, imatrix;
179       ZoomIndex _zoomIndex;
180       ZoomState _previousLogicalZoom { ZoomIndex::ZOOM_PAGE_WIDTH, 0.0 }; // for zoom-level toggling
181 
182       QFocusFrame* focusFrame;
183 
184       EditData editData;
185       std::vector<std::unique_ptr<ElementGroup>> dragGroups;
186 
187       //--input state:
188       PositionCursor* _cursor;
189 
190       PositionCursor* _controlCursor;
191       SmoothPanSettings _panSettings;
192       double _timeElapsed;
193       double _controlModifier;      // a control modifier of 1 means that the cursor is moving at it's normal speed
194                                     // if all measures are of the same size, this will stay equal to 1 (unless the distance settings are changed, and make the algorithm over-sensitive)
195       double _playbackCursorOldPosition;
196       double _playbackCursorNewPosition;
197       double _playbackCursorDistanceTravelled;
198 
199       ShadowNote* shadowNote;
200 
201       // Realtime state:      Note: always set allowRealtimeRests to desired value before starting a timer.
202       QTimer* realtimeTimer;   // multi-shot timer for advancing in automatic realtime mode
203       QTimer* extendNoteTimer; // single-shot timer for initial advancement when a note is held
204       bool allowRealtimeRests; // Allow entering rests in realtime mode? (See note above)
205 
206       bool tripleClickPending = false;
207       bool popupActive = false;
208       bool modifySelection = false;
209       Element* elementToSelect = nullptr;
210 
211       // Loop In/Out marks in the score
212       PositionCursor* _curLoopIn;
213       PositionCursor* _curLoopOut;
214 
215       // Continuous panel
216       ContinuousPanel* _continuousPanel;
217 
218       Lasso* lasso;           ///< temporarily drawn lasso selection
219       FotoLasso* _foto;
220 
221       QColor _bgColor;
222       QColor _fgColor;
223       QPixmap* _bgPixmap;
224       QPixmap* _fgPixmap;
225 
226       // By default when the view will prevent viewpoint changes if
227       // it is inactive. Set this flag to true to change this behaviour.
228       bool _moveWhenInactive = false;
229 
230       bool _blockShowEdit = false;
231 
232       virtual void paintEvent(QPaintEvent*);
233       void paint(const QRect&, QPainter&);
234 
235       void objectPopup(const QPoint&, Element*);
236       void measurePopup(QContextMenuEvent* ev, Measure*);
237 
238       void saveChord(XmlWriter&);
239 
240       virtual bool event(QEvent* event) override;
241       virtual bool gestureEvent(QGestureEvent*);            // ??
242       virtual void resizeEvent(QResizeEvent*) override;
243       virtual void dragEnterEvent(QDragEnterEvent*) override;
244       virtual void dragLeaveEvent(QDragLeaveEvent*) override;
245       virtual void dragMoveEvent(QDragMoveEvent*) override;
246       virtual void dropEvent(QDropEvent*) override;
247       virtual void focusInEvent(QFocusEvent*) override;
248       virtual void focusOutEvent(QFocusEvent*) override;
249 
250       virtual void wheelEvent(QWheelEvent*) override;
251       virtual void mouseMoveEvent(QMouseEvent*) override;
252       virtual void mousePressEvent(QMouseEvent*) override;
253       virtual void mouseReleaseEvent(QMouseEvent*) override;
254       virtual void mouseDoubleClickEvent(QMouseEvent*);
255 
256       virtual void keyPressEvent(QKeyEvent*) override;
257       virtual void keyReleaseEvent(QKeyEvent*) override;
258       virtual void inputMethodEvent(QInputMethodEvent*) override;
259 
260       bool handleArrowKeyPress(const QKeyEvent*);
261 
262       virtual void contextMenuEvent(QContextMenuEvent*) override;
263 
264       void mousePressEventNormal(QMouseEvent*);
265       void escapeCmd();
266       bool startTextEditingOnMouseRelease(QMouseEvent*);
267       void adjustCursorForTextEditing(QMouseEvent*);
268 
269       void constraintCanvas(int *dxx, int *dyy);
270 
271       void setShadowNote(const QPointF&);
272       void drawElements(QPainter& p,QList<Element*>& el, Element* editElement);
273       bool dragTimeAnchorElement(const QPointF& pos);
274       bool dragMeasureAnchorElement(const QPointF& pos);
275       virtual void lyricsTab(bool back, bool end, bool moveOnly) override;
276       virtual void lyricsReturn() override;
277       virtual void lyricsEndEdit() override;
278       virtual void lyricsUpDown(bool up, bool end) override;
279       virtual void lyricsMinus() override;
280       virtual void lyricsUnderscore() override;
281       virtual void textTab(bool back = false) override;
282       void harmonyTab(bool back);
283       void harmonyBeatsTab(bool noterest, bool back);
284       void harmonyTicksTab(const Fraction& ticks);
285       void figuredBassTab(bool meas, bool back);
286       void figuredBassTicksTab(const Fraction& ticks);
287       void realtimeAdvance(bool allowRests);
288       void cmdAddFret(int fret);
289       void cmdAddChordName(HarmonyType ht);
290       void cmdAddText(Tid tid, Tid customTid = Tid::DEFAULT, PropertyFlags pf = PropertyFlags::STYLED, Placement p = Placement::ABOVE);
291       void cmdEnterRest(const TDuration&);
292       void cmdEnterRest();
293       void cmdTuplet(int n, ChordRest*);
294       void cmdTuplet(int);
295       void cmdCreateTuplet(ChordRest* cr, Tuplet* tuplet);
296       void cmdRepeatSelection();
297       void cmdChangeEnharmonic(bool);
298 
299       MeasureBase* insertMeasure(ElementType, MeasureBase*);
300       MeasureBase* checkSelectionStateForInsertMeasure();
301 
302       void appendMeasures(int, ElementType);
303       MeasureBase* appendMeasure(ElementType);
304       void cmdInsertMeasure(ElementType);
305       void createElementPropertyMenu(Element* e, QMenu*);
306       void genPropertyMenu1(Element* e, QMenu* popup);
307       void genPropertyMenuText(Element* e, QMenu* popup);
308       void elementPropertyAction(const QString&, Element* e);
309       void paintPageBorder(QPainter& p, Page* page);
310       bool dropCanvas(Element*);
311       void editCmd(const QString&);
312       void setLoopCursor(PositionCursor* curLoop, const Fraction& tick, bool isInPos);
313       void cmdMoveCR(bool left);
314       void cmdGotoElement(Element*);
315       bool checkCopyOrCut();
316       QVariant inputMethodQuery(Qt::InputMethodQuery query) const override;
317       void startFotomode();
318       void stopFotomode();
319       void startFotoDrag();
320       void endFotoDrag();
321       void endFotoDragEdit();
322       QImage getRectImage(const QRectF& rect, double dpi, bool transparent, bool printMode);
323 
324       void startEdit(bool editMode = true);
325       void endEdit();
326 
327       void startDrag();
328       void endDrag();
329 
330       void endDragEdit();
331 
332       void startNoteEntry();
333       virtual void startNoteEntryMode() override;
334       void endNoteEntry();
335 
336       void endLasso();
337       Element* getDropTarget(EditData&);
338 
339    private slots:
340       void posChanged(POS pos, unsigned tick);
341       void loopToggled(bool);
342       void triggerCmdRealtimeAdvance();
343       void cmdRealtimeAdvance();
344       void extendCurrentNote();
345       void seqStopped();
346       void tripleClickTimeOut();
347 
348    public slots:
349       void setViewRect(const QRectF&);
350 
351       void deselectAll();
352 
353       void editCopy();
354       void editCut();
355       void editPaste();
356       void editSwap();
357 
358       void normalCut();
359       void normalCopy();
360       void fotoModeCopy(bool includeLink = false);
361       bool normalPaste(Fraction scale = Fraction(1, 1));
362       void normalSwap();
363 
364       void setControlCursorVisible(bool v);
365 
366       void cloneElement(Element* e);
367       void doFotoDragEdit(QMouseEvent* ev);
368 
369       void updateContinuousPanel();
370       void ticksTab(const Fraction& ticks);     // helper function
371 
372    signals:
373       void viewRectChanged();
374       void scaleChanged(double);
375       void offsetChanged(double, double);
376       void sizeChanged();
377 
378    public:
379       ScoreView(QWidget* parent = 0);
380       ~ScoreView();
381 
fgPixmap()382       QPixmap* fgPixmap() { return _fgPixmap; }
383 
384       void startEdit(Element*, Grip) override;
385       void startEditMode(Element*);
386 
387       void moveCursor(const Fraction& tick);
388       void moveControlCursor(const Fraction& tick);
389       bool isCursorDistanceReasonable();
390       void moveControlCursorNearCursor();
391       Fraction cursorTick() const;
392       void setCursorOn(bool);
393       void setBackground(QPixmap*);
394       void setBackground(const QColor&);
395       void setForeground(QPixmap*);
396       void setForeground(const QColor&);
397 
398       Page* addPage();
399       virtual void setScore(Score* s);
removeScore()400       virtual void removeScore()  { _score = 0; }
401 
402       void setPhysicalZoomLevel(qreal logicalLevel);
403 
404       bool navigatorVisible() const;
405       void cmd(const QAction*);
406       void cmd(const char*);
407 
408       void startUndoRedo(bool);
409       void zoomBySteps(qreal numSteps, bool usingMouse = false, const QPointF& pos = QPointF());
410       void setLogicalZoom(ZoomIndex index, qreal logicalLevel, const QPointF& pos = QPointF());
411       qreal calculateLogicalZoomLevel(const ZoomIndex index, const qreal logicalFreeZoomLevel = 0.0) const;
412       qreal calculatePhysicalZoomLevel(const ZoomIndex index, const qreal logicalFreeZoomLevel = 0.0) const;
413       void contextPopup(QContextMenuEvent* ev);
414       bool editKeyLyrics();
415       bool editKeySticking();
416       void dragScoreView(QMouseEvent* ev);
417       void doDragElement(QMouseEvent* ev);
418       void doDragLasso(QMouseEvent* ev);
419       void doDragFoto(QMouseEvent* ev);
420       void doDragEdit(QMouseEvent* ev);
421       bool testElementDragTransition(QMouseEvent* ev);
422       bool fotoEditElementDragTransition(QMouseEvent* ev);
423       void cmdAddSlur(const Slur* slurTemplate = nullptr);
424       void addSlur(ChordRest*, ChordRest*, const Slur*) override;
425       virtual void cmdAddHairpin(HairpinType);
426       void cmdAddNoteLine();
427 
428       void setEditElement(Element*);
429       void updateEditElement();
430 
431       bool wasShown = false;
noteEntryMode()432       bool noteEntryMode() const { return state == ViewState::NOTE_ENTRY; }
editMode()433       bool editMode() const      { return state == ViewState::EDIT; }
textEditMode()434       bool textEditMode() const  { return editMode() && editData.element && editData.element->isTextBase(); }
hasEditGrips()435       bool hasEditGrips() const  { return editData.element && editData.grips; }
436       bool fotoMode() const;
437 
438       virtual void setDropRectangle(const QRectF&);
439       virtual void setDropTarget(const Element*) override;
440       void setDropAnchorLines(const QVector<QLineF> &anchorList);
matrix()441       const QTransform& matrix() const  { return _matrix; }
442 
zoomIndex()443       ZoomIndex zoomIndex() const { return _zoomIndex; }
444       qreal logicalZoomLevel() const;
445       qreal physicalZoomLevel() const;
logicalZoom()446       ZoomState logicalZoom() const { return { _zoomIndex, logicalZoomLevel() }; }
setLogicalZoom(const ZoomState & logicalZoom)447       void setLogicalZoom(const ZoomState& logicalZoom) { setLogicalZoom(logicalZoom.index, logicalZoom.level); }
448 
previousZoomIndex()449       ZoomIndex previousZoomIndex() const { return _previousLogicalZoom.index; }
previousLogicalZoomLevel()450       qreal previousLogicalZoomLevel() const { return _previousLogicalZoom.level; }
previousLogicalZoom()451       const ZoomState& previousLogicalZoom() const { return _previousLogicalZoom; }
setPreviousLogicalZoom(ZoomState previousLogicalZoom)452       void setPreviousLogicalZoom(ZoomState previousLogicalZoom) { _previousLogicalZoom = std::move(previousLogicalZoom); }
453 
454       qreal xoffset() const;
455       qreal yoffset() const;
456       void setOffset(qreal x, qreal y);
457       QSizeF fsize() const;
458       void screenNext();
459       void screenPrev();
460       void pageNext();
461       void pagePrev();
462       void pageTop();
463       void pageEnd();
toLogical(const QPoint & p)464       QPointF toLogical(const QPoint& p) const   { return imatrix.map(QPointF(p)); }
toPhysical(const QPointF & p)465       QPointF toPhysical(const QPointF& p) const {return _matrix.map(p); }
toLogical(const QRectF & r)466       QRectF toLogical(const QRectF& r) const    { return imatrix.mapRect(r); }
toPhysical(const QRectF & r)467       QRect toPhysical(const QRectF& r) const    { return _matrix.mapRect(r).toRect(); }
468 
canvasViewport()469       QRectF canvasViewport() const { return toLogical(geometry()); }
470 
471       bool searchMeasure(int i);
472       bool searchPage(int i);
473       bool searchRehearsalMark(const QString& s);
474       void gotoMeasure(Measure*);
475       void setFocusRect();
476       void changeVoice(int voice);
477       virtual void drawBackground(QPainter* p, const QRectF& r) const;
478       bool fotoScoreViewDragTest(QMouseEvent*);
479       bool fotoScoreViewDragRectTest(QMouseEvent*);
480       void doDragFotoRect(QMouseEvent*);
481       void fotoContextPopup(QContextMenuEvent*);
482       bool fotoRectHit(const QPoint& p);
483       void paintRect(bool printMode, QPainter& p, const QRectF& r, double mag);
484       bool saveFotoAs(bool printMode, const QRectF&);
485       void fotoDragDrop(QMouseEvent*);
486       void changeEditElement(Element*);
487 
488       void cmdAppendMeasures(int, ElementType);
489       void cmdInsertMeasures(int, ElementType);
490 
491       void cmdAddRemoveBreaks();
492       void cmdCopyLyricsToClipboard();
493 
494       ScoreState mscoreState() const;
495       void setCursorVisible(bool v);
496       void showOmr(bool flag);
497       void midiNoteReceived(int pitch, bool chord, int velocity);
498 
499       virtual void moveCursor() override;
500 
panSettings()501       SmoothPanSettings& panSettings() { return _panSettings; }
502 
503       virtual void layoutChanged();
504       virtual void dataChanged(const QRectF&);
updateAll()505       virtual void updateAll()    { update(); }
506       virtual void adjustCanvasPosition(const Element* el, bool playBack, int staff = -1) override;
setCursor(const QCursor & c)507       virtual void setCursor(const QCursor& c) { QWidget::setCursor(c); }
cursor()508       virtual QCursor cursor() const { return QWidget::cursor(); }
loopUpdate(bool val)509       void loopUpdate(bool val)   {  loopToggled(val); }
510 
511       void moveViewportToLastEdit();
512 
513       void updateShadowNotes();
514 
omrView()515       OmrView* omrView() const        { return _omrView; }
setOmrView(OmrView * v)516       void setOmrView(OmrView* v)     { _omrView = v;    }
fotoLasso()517       FotoLasso* fotoLasso() const    { return _foto;    }
518       Element* getEditElement();
519       void onElementDestruction(Element*) override;
520 
521       virtual Element* elementNear(QPointF);
522       QList<Element*> elementsNear(QPointF);
523       void editArticulationProperties(Articulation*);
524       void editTimeSigProperties(TimeSig*);
525       void editStaffTextProperties(StaffTextBase*);
526       void selectInstrument(InstrumentChange*);
getEditData()527       EditData& getEditData()        { return editData; }
528       void changeState(ViewState);
529 
geometry()530       virtual const QRect geometry() const override { return QWidget::geometry(); }
531 
532       void updateGrips();
moveWhenInactive()533       bool moveWhenInactive() const { return _moveWhenInactive; }
moveWhenInactive(bool move)534       bool moveWhenInactive(bool move) { bool m = _moveWhenInactive; _moveWhenInactive = move; return m; }
535 
536       QElapsedTimer _controlCursorTimer, _playbackCursorTimer;
537       friend struct SmoothPanSettings;
538 
539       private:
540          void drawAnchorLines(QPainter& painter);
541       };
542 
543 } // namespace Ms
544 #endif
545 
546