1 //========================================================= 2 // MusE 3 // Linux Music Editor 4 // $Id: ctrlcanvas.h,v 1.7.2.4 2009/06/01 20:15:53 spamatica Exp $ 5 // (C) Copyright 1999 Werner Schweer (ws@seh.de) 6 // 7 // This program is free software; you can redistribute it and/or 8 // modify it under the terms of the GNU General Public License 9 // as published by the Free Software Foundation; version 2 of 10 // the License, or (at your option) any later version. 11 // 12 // This program is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 // 17 // You should have received a copy of the GNU General Public License 18 // along with this program; if not, write to the Free Software 19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 // 21 //========================================================= 22 23 #ifndef __CTRLCANVAS_H__ 24 #define __CTRLCANVAS_H__ 25 26 #include <set> 27 28 #include "type_defs.h" 29 #include "view.h" 30 #include "tools.h" 31 #include "midictrl.h" 32 #include "event.h" 33 #include "citem.h" 34 #include "undo.h" 35 #include "event_tag_list.h" 36 37 class QWheelEvent; 38 class QMouseEvent; 39 class QEvent; 40 class QWidget; 41 class QLabel; 42 43 namespace MusECore { 44 class Event; 45 class MidiPart; 46 class MidiTrack; 47 class PartList; 48 } 49 50 namespace MusEGui { 51 52 class CtrlPanel; 53 class MidiEditor; 54 class PopupMenu; 55 56 //--------------------------------------------------------- 57 // CEvent 58 // ''visual'' Controller Event 59 //--------------------------------------------------------- 60 61 class CEvent : public CItem { 62 private: 63 MusECore::Event _event; 64 int _val; 65 MusECore::Part* _part; 66 int ex; 67 68 public: 69 CEvent(const MusECore::Event&, MusECore::Part*, int v); 70 CEvent(); 71 bool isObjectInRange(const MusECore::Pos&, const MusECore::Pos&) const; objectIsSelected()72 bool objectIsSelected() const { return _event.selected(); } 73 val()74 int val() const { return _val; } setVal(int v)75 void setVal(int v) { _val = v; } setEX(int v)76 void setEX(int v) { ex = v; } 77 bool containsPoint(const MusECore::MidiController* mc, const QPoint& p, const int tickstep, const int wh) const; 78 bool containsXRange(int x1, int x2) const; 79 bool intersectsController(const MusECore::MidiController*, const QRect&, const int tickstep, const int windowHeight) const; EX()80 int EX() { return ex; } 81 event()82 MusECore::Event event() const { return _event; } 83 // HACK This returns a clone of the event with the length set to the visual length. 84 // It should only be used for temporary things like copy/paste and the length 85 // value should be reset to zero after usage. 86 // Normally an event's length is ALWAYS zero for all controller events. 87 MusECore::Event eventWithLength() const; setEvent(const MusECore::Event & e)88 void setEvent(const MusECore::Event& e) { _event = e; } part()89 MusECore::Part* part() const { return _part; } setPart(MusECore::Part * p)90 void setPart(MusECore::Part* p) { _part = p; } 91 }; 92 93 //--------------------------------------------------------- 94 // CtrlCanvas 95 //--------------------------------------------------------- 96 97 class CtrlCanvas : public MusEGui::View { 98 Q_OBJECT 99 100 Q_PROPERTY( quint8 bgAlpha READ bgAlpha WRITE setBgAlpha ) 101 102 public: 103 104 //--------------------------------------------------------- 105 // CtrlCanvasInfoStruct 106 // Structure for returning info from CtrlCanvas::getCtrlInfo() 107 //--------------------------------------------------------- 108 109 struct CtrlCanvasInfoStruct 110 { 111 int fin_ctrl_num; 112 bool is_newdrum_ctl; 113 int min; 114 int max; 115 int bias; 116 CtrlCanvasInfoStructCtrlCanvasInfoStruct117 CtrlCanvasInfoStruct() : fin_ctrl_num(0), is_newdrum_ctl(false), min(0), max(127), bias(0) {} 118 }; 119 120 private: 121 MidiEditor* editor; 122 MusECore::MidiTrack* curTrack; 123 MusECore::MidiPart* curPart; 124 MusECore::MidiCtrlValList* ctrl; 125 MusECore::MidiController* _controller; 126 CtrlPanel* _panel; 127 int _cnum; 128 int _dnum; // Current real drum controller number (anote). 129 int _didx; // Current real drum controller index. 130 // For current part. 131 CtrlCanvasInfoStruct _ctrlInfo; 132 133 int line1x; 134 int line1y; 135 int line2x; 136 int line2y; 137 bool drawLineMode; 138 bool noEvents; 139 bool filterTrack; 140 // Whether we have grabbed the mouse. 141 bool _mouseGrabbed; 142 // The number of times we have called QApplication::setOverrideCursor(). 143 // This should always be one or zero, anything else is an error, but unforeseen 144 // events might cause us to miss a decrement with QApplication::restoreOverrideCursor(). 145 int _cursorOverrideCount; 146 quint8 _bgAlpha; 147 148 QPoint _curDragOffset; 149 unsigned int _dragFirstXPos; 150 //Qt::CursorShape _cursorShape; 151 152 static const int overlayTextOffsetFromOrg; 153 154 void applyYOffset(MusECore::Event& e, int yoffset) const; 155 156 void viewMousePressEvent(QMouseEvent* event); 157 void viewMouseMoveEvent(QMouseEvent*); 158 void viewMouseReleaseEvent(QMouseEvent*); 159 virtual void wheelEvent(QWheelEvent*); 160 161 virtual void draw(QPainter&, const QRect& rect, const QRegion& = QRegion()); 162 virtual void pdraw(QPainter&, const QRect&, const QRegion& = QRegion()); 163 virtual void drawOverlay(QPainter&, const QRect&, const QRegion& = QRegion()); 164 virtual QRect overlayRect() const; 165 166 void changeValRamp(int x1, int x2, int y1, int y2); 167 void newValRamp(int x1, int y1, int x2, int y2); 168 void changeVal(int x1, int x2, int y); 169 void newVal(int x1, int y); 170 void newVal(int x1, int y1, int x2, int y2); 171 void deleteVal(int x1, int x2, int y); 172 173 bool setCurTrackAndPart(); 174 void drawMoving(QPainter& p, const QRect& rect, const QRegion& region, const MusECore::MidiPart* part); 175 void pdrawItems(QPainter& p, const QRect& rect, const MusECore::MidiPart* part, bool velo, bool fg); 176 void pFillBackgrounds(QPainter& p, const QRect& rect, const MusECore::MidiPart* part); 177 void pdrawExtraDrumCtrlItems(QPainter& p, const QRect& rect, const MusECore::MidiPart* part, int drum_ctl); 178 void partControllers( 179 const MusECore::MidiPart* part, int num, 180 int* dnum, int* didx, 181 MusECore::MidiController** mc, MusECore::MidiCtrlValList** mcvl, 182 CtrlCanvasInfoStruct* ctrlInfo); 183 // Checks if the current drum pitch requires setting the midi controller and rebuilding the items. 184 // Returns whether setMidiController() and updateItems() were in fact called. 185 bool drumPitchChanged(); 186 CEvent* findCurrentItem(const QPoint& p, const int tickstep, const int h); 187 // If show is true, calls QApplication::restoreOverrideCursor() until _cursorOverrideCount-- is <= 0. 188 // If show is false, calls QApplication::setOverrideCursor with a blank cursor. 189 void showCursor(bool show = true); 190 // Sets or resets the _mouseGrabbed flag and grabs or releases the mouse. 191 void setMouseGrab(bool grabbed = false); 192 193 protected: 194 enum DragMode { DRAG_OFF, DRAG_NEW, DRAG_MOVE_START, DRAG_MOVE, 195 DRAG_DELETE, DRAG_COPY_START, DRAG_COPY, 196 DRAGX_MOVE, DRAGY_MOVE, 197 DRAGX_COPY, DRAGY_COPY, 198 DRAG_RESIZE, DRAG_LASSO_START, DRAG_LASSO, 199 DRAG_PAN, DRAG_ZOOM 200 }; 201 202 enum DragType { 203 MOVE_MOVE, MOVE_COPY 204 }; 205 206 enum ContextIds { 207 ContextIdCancelDrag = 0x01, 208 ContextIdMerge = 0x02, 209 ContextIdMergeCopy = 0x04, 210 ContextIdErase = 0x08, 211 ContextIdEraseWysiwyg = 0x10, 212 ContextIdEraseInclusive = 0x20 213 }; 214 215 CItemList items; 216 // To avoid working directly with a potentially huge number of items 217 // in the item list, these 'indexing' lists are used instead. 218 CItemList selection; 219 CItemList moving; 220 221 CEvent* curItem; 222 CEvent* _movingItemUnderCursor; 223 224 DragMode drag; 225 DragType _dragType; 226 QRect lasso; 227 QPoint start; 228 QPoint _mouseDist; 229 MusEGui::Tool tool; 230 unsigned pos[3]; 231 int curDrumPitch; //Used by the drum-editor to view velocity of only one key (one drum) 232 bool _perNoteVeloMode; 233 234 // Accumulated operations during drawing etc. 235 MusECore::Undo _operations; 236 237 void setCursor(); 238 void keyPressEvent(QKeyEvent *event); 239 void keyReleaseEvent(QKeyEvent *event); 240 void enterEvent(QEvent*e); 241 void leaveEvent(QEvent*e); 242 QPoint raster(const QPoint&) const; 243 244 // selection isSingleSelection()245 bool isSingleSelection() { return selection.size() == 1; } 246 void deselectAll(); 247 void selectItem(CEvent* e); 248 void deselectItem(CEvent* e); 249 void removeSelection(CEvent* e); 250 251 void setMidiController(int); 252 void updateItems(); 253 // Inform the app if local items have changed and their corresponding 254 // objects need to be updated synchronously in the audio thread. 255 // Returns true if anything changed (or will change). 256 // Uses an internal undo operations list or optionally with a supplied list 257 // so operations can be chained. 258 bool itemSelectionsChanged(MusECore::Undo* operations = 0, bool deselectAll = false); 259 void updateItemSelections(); 260 261 // moving 262 void startMoving(const QPoint&, int dir, bool rasterize = true); 263 void moveItems(const QPoint&, int dir = 0, bool rasterize = true); 264 void endMoveItems(); 265 MusECore::Undo moveCanvasItems(CItemList&, int, int, DragType, bool rasterize = true); 266 bool moveItem(MusECore::Undo&, CItem*, const QPoint&, DragType, bool rasterize = true); 267 // Resets the moving flag of all items in moving list, then clears the list. 268 // Returns true if anything was changed. 269 bool clearMoving(); 270 // Resets all mouse operations if detecting missed mouseRelease event (which DOES happen). 271 // Returns true if reset was actually done. 272 bool cancelMouseOps(); 273 274 // Populates a popup menu with items related to drag/drop merging. 275 void populateMergeOptions(PopupMenu* menu); 276 277 // Merges any dragged items. Merges copies of items if 'copy' is true. Otherwise moves the items. 278 // Returns true if items were merged, and it was successful. False if no items were moving, or error. 279 bool mergeDraggedItems(bool copy); 280 281 private slots: 282 void songChanged(MusECore::SongChangedStruct_t type); 283 void configChanged(); 284 // Returns whether setMidiController() and updateItems() were in fact called, via drumPitchChanged(). 285 bool setCurDrumPitch(int); 286 287 public slots: 288 void setTool(int t); 289 void setPos(int, unsigned, bool adjustScrollbar); 290 void setController(int ctrl); 291 void curPartHasChanged(MusECore::Part*); 292 293 signals: 294 void followEvent(int); 295 void xposChanged(unsigned); 296 void yposChanged(int); 297 void redirectWheelEvent(QWheelEvent*); 298 299 public: 300 CtrlCanvas(MidiEditor*, QWidget* parent, int, 301 const char* name = 0, CtrlPanel* pnl = 0); 302 ~CtrlCanvas(); 303 void setPanel(CtrlPanel* pnl); ctrlValList()304 MusECore::MidiCtrlValList* ctrlValList() { return ctrl; } controller()305 MusECore::MidiController* controller() { return _controller; } track()306 MusECore::MidiTrack* track() const { return curTrack; } getCurDrumPitch()307 int getCurDrumPitch() const { return curDrumPitch; } perNoteVeloMode()308 bool perNoteVeloMode() const { return _perNoteVeloMode; } 309 void setPerNoteVeloMode(bool); itemsAreSelected()310 bool itemsAreSelected() const { return !selection.empty(); } 311 // Appends given tag list with item objects according to options. Avoids duplicate events or clone events. 312 // Special: We 'abuse' a controller event's length, normally 0, to indicate visual item length. 313 void tagItems(MusECore::TagEventList* tag_list, const MusECore::EventTagOptionsStruct& options) const; 314 bgAlpha()315 quint8 bgAlpha() const { return _bgAlpha; } setBgAlpha(const quint8 a)316 void setBgAlpha(const quint8 a) { _bgAlpha = a; } 317 }; 318 319 } // namespace MusEGui 320 321 #endif 322 323