/* EventMap Widget * Copyleft (C) 2001 David Griffiths * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "Fl_EventMap.h" #include #include #include #include static const int AREA_WIDTH = 1000; static const int AREA_HEIGHT = 1000; static const int BUTTON_COLOUR = 10; static const int EVENT_COLOUR = 0; static const int BG_COLOUR = 139; static const int LINE_COLOUR = 140; //////////////////////////////////////////////////////////////////// Fl_EventMap::Fl_EventMap(int x, int y, int w, int h, const char* label) : Fl_Group(x,y,w,h,label), m_SeqPointer(NULL), m_Type(ARRANGE_MAP), m_Update(true), m_Zoom(1.0f), m_GridSizeX(0), m_GridSizeY(10), m_PixelsPerSec(100), m_NextID(0), m_StartLoop(1.0f), m_EndLoop(2.0f), m_Pos(0), m_LastPos(0), m_DrawBeats(false), m_BarLength(100), m_BeatsBar(8), cb_NewEvent(NULL), cb_RightMouse(NULL), cb_CopyEvent(NULL), m_FirstUpdate(true) { // white/black keys for the melody m_KeyColMap[0] = FL_YELLOW; m_KeyColMap[1] = FL_BLUE; m_KeyColMap[2] = FL_YELLOW; m_KeyColMap[3] = FL_BLUE; m_KeyColMap[4] = FL_YELLOW; m_KeyColMap[5] = FL_BLUE; m_KeyColMap[6] = FL_YELLOW; m_KeyColMap[7] = FL_YELLOW; m_KeyColMap[8] = FL_BLUE; m_KeyColMap[9] = FL_YELLOW; m_KeyColMap[10] = FL_BLUE; m_KeyColMap[11] = FL_YELLOW; } void Fl_EventMap::CreateWindow() { int yoff=0; //m_StartTri = new Fl_TriEvent(90, 5, 20, 10, ""); //m_StartTri->LockY(); //m_StartTri->SetResizeGrab(0); //m_StartTri->SetPixelsPerSec(m_PixelsPerSec,true); m_PosTri = new Fl_TriEvent(90, 5, 30, 20, ""); m_PosTri->LockY(); m_PosTri->SetResizeGrab(0); m_PosTri->SetPixelsPerSec(m_PixelsPerSec,true); m_EndTri = new Fl_TriEvent(50, 5, 20, 10, ""); m_EndTri->LockY(); m_EndTri->SetResizeGrab(0); m_EndTri->SetPixelsPerSec(m_PixelsPerSec,true); show(); } void Fl_EventMap::draw() { clear_damage(FL_DAMAGE_ALL); fl_color(BG_COLOUR); fl_rectf(x(),y(),w(),h()); // draw the section markers fl_color(LINE_COLOUR); if (m_GridSizeY) { // draw the snap points for (int n=y(); nGetStartTime(); //m_EndLoop=m_EndTri->GetStartTime(); int StartPixels=(int)(m_StartLoop*(float)m_PixelsPerSec)+x(); int EndPixels=(int)(m_EndLoop*(float)m_PixelsPerSec)+x(); fl_line(StartPixels,y()+15,StartPixels,y()+h()); fl_line(EndPixels,y()+15,EndPixels,y()+h()); } Fl_Group::draw(); SetFirstUpdate(); } int Fl_EventMap::handle(int event) { if (!Fl_Group::handle(event) && event==FL_PUSH) { if (m_Type!=ARRANGE_MAP) { AddEvent(Fl::event_x(),Fl::event_y(),20, Fl_SEvent::NO_TYPE); } } for (map::iterator i=m_EventMap.begin(); i!=m_EventMap.end(); i++) { Fl_SEvent *pEvent = i->second; if (pEvent->Killed()) { RemoveEvent(i->first); } } return event; } void Fl_EventMap::SetZoomLevel(float s) { m_Zoom=s; m_PixelsPerSec=int(100/m_Zoom); vector EventVec; for (map::iterator i=m_EventMap.begin(); i!=m_EventMap.end(); i++) { i->second->SetPixelsPerSec(m_PixelsPerSec); } //m_StartTri->SetPixelsPerSec(m_PixelsPerSec); m_EndTri->SetPixelsPerSec(m_PixelsPerSec); redraw(); } void Fl_EventMap::SetSnapGap(float s) { m_GridSizeX=(int)(s*(float)m_PixelsPerSec); for (map::iterator i=m_EventMap.begin(); i!=m_EventMap.end(); i++) { i->second->SetSnapGap(s); } redraw(); } vector Fl_EventMap::GetEvents(float Time) { assert(m_PixelsPerSec!=0); m_Pos = (int)(Time*m_PixelsPerSec); // line marker update // all in all, some orrible code... if (m_Update && window()->visible() && m_Pos!=m_LastPos) { window()->make_current(); int DrawPos=m_Pos+x(); m_PosTri->resize(DrawPos,m_PosTri->y(),m_PosTri->w(),m_PosTri->h()); redraw(); /* if (DrawPos>m_ClipX && DrawPosmake_current(); } m_FirstUpdate=false; vector EventVec; for (map::iterator i=m_EventMap.begin(); i!=m_EventMap.end(); i++) { Fl_SEvent *pEvent = i->second; bool State=pEvent->UpdateState(Time); EventInfo::Type type=EventInfo::ON; if (pEvent->AtStart()) type=EventInfo::START; if (pEvent->AtEnd()) type=EventInfo::END; // Collect the events happening now, or just finished if(State || pEvent->AtEnd()) { EventVec.push_back(EventInfo(pEvent->GetID(),pEvent->GetGroup(), type,pEvent->GetStartTime())); } } return EventVec; } int Fl_EventMap::GetGroupFromY(int y) { return y/m_GridSizeY; } int Fl_EventMap::AddEventTime(float st, int g, float lt, Fl_SEvent::Type EType, bool CallBack) { int ex,ey,ew; ex=(int)(st*(float)m_PixelsPerSec)+x(); ew=(int)(lt*(float)m_PixelsPerSec); ey=g*m_GridSizeY+y(); return AddEvent(ex, ey, ew, EType, CallBack); } int Fl_EventMap::AddEvent(int x, int y, int w, Fl_SEvent::Type EType, bool CallBack) { Fl_SEvent *NewEvent; if (m_Type==PERCUSSION_MAP) { NewEvent = new Fl_CircEvent(x,y,w,m_GridSizeY); } else { NewEvent = new Fl_SEvent(x,y,w,m_GridSizeY); } if (m_Type==MELODY_MAP) NewEvent->LockResize(false); NewEvent->SetPixelsPerSec(m_PixelsPerSec, true); NewEvent->color(EVENT_COLOUR); NewEvent->labelsize(10); NewEvent->SetID(m_NextID++); NewEvent->SetType(EType); char Name[256]; if (m_Type==ARRANGE_MAP) { if(NewEvent->GetType()==Fl_SEvent::MELODY) sprintf(Name,"Melody %d",NewEvent->GetID()); if(NewEvent->GetType()==Fl_SEvent::PERCUSSION) sprintf(Name,"Percussion %d",NewEvent->GetID()); } else sprintf(Name,"This shouldnt be read!"); NewEvent->SetName(Name); NewEvent->SetGridX(m_GridSizeX); NewEvent->SetGridY(m_GridSizeY); map::iterator i=m_EventMap.find(NewEvent->GetID()); if (i!=m_EventMap.end()) { cerr<<"Event ID not unique, not added!"<SnapX(); NewEvent->SnapY(); NewEvent->SetPixelsPerSec(m_PixelsPerSec,true); m_EventMap[NewEvent->GetID()]=NewEvent; int ID = NewEvent->GetID(); if (cb_NewEvent && CallBack) cb_NewEvent(NewEvent,&ID); redraw(); return NewEvent->GetID(); } void Fl_EventMap::CopyEvent(int x, int y, int w, int ID, float LengthTime) { // make the new widget int NewID = AddEvent(x,y,w,m_EventMap[ID]->GetType(),false); // set the length of time exactly, as rounding // errors cause a reinit of the sample memory GetEvent(NewID)->SetLengthTime(LengthTime); //string Name="Copy of "+m_EventMap[ID]->GetName(); //GetEvent(NewID)->SetName(Name); GetEvent(NewID)->SetName(m_EventMap[ID]->GetName()); if (cb_CopyEvent) cb_CopyEvent(GetEvent(NewID),&ID); } void Fl_EventMap::RemoveAllEvents() { for (map::iterator i=m_EventMap.begin(); i!=m_EventMap.end(); i++) { Fl_SEvent *e=i->second; remove(e); m_EventMap.erase(i); delete(e); } m_EventMap.clear(); m_NextID=0; redraw(); } void Fl_EventMap::RemoveEvent(int ID) { map::iterator i=m_EventMap.find(ID); if (i==m_EventMap.end()) { cerr<<"Event ID not found to delete"<second; remove(e); m_EventMap.erase(i); delete(e); } Fl_SEvent *Fl_EventMap::GetEvent(int ID) { map::iterator i=m_EventMap.find(ID); if (i==m_EventMap.end()) { cerr<<"Event ID not found"<SetLengthTime(l); } void Fl_EventMap::CopyFrom(Fl_EventMap *Other) { m_Type = Other->m_Type; m_Zoom = Other->m_Zoom; m_GridSizeX = Other->m_GridSizeX; m_GridSizeY = Other->m_GridSizeY; m_PixelsPerSec = Other->m_PixelsPerSec; m_StartLoop = Other->m_StartLoop; m_EndLoop = Other->m_EndLoop; m_Pos = Other->m_Pos; m_LastPos = Other->m_LastPos; m_BarLength = Other->m_BarLength; m_BeatsBar = Other->m_BeatsBar; m_NextID = Other->m_NextID; for (map::iterator i=Other->m_EventMap.begin(); i!=Other->m_EventMap.end(); i++) { Fl_SEvent *NewEvent; if (m_Type==PERCUSSION_MAP) { NewEvent = new Fl_CircEvent(*(Fl_CircEvent*)i->second); } else { NewEvent = new Fl_SEvent(*i->second); } add(NewEvent); m_EventMap[NewEvent->GetID()]=NewEvent; } } ///////////////////////////////////////////////////// istream &operator>>(istream &s, Fl_EventMap &o) { string dummy; s>>dummy; if (dummy!="EventMap") cerr<<"Error in stream before Fl_EventMap"<>(int&)o.m_Type; s>>o.m_Zoom; s>>o.m_GridSizeX; s>>o.m_GridSizeY; s>>o.m_PixelsPerSec; s>>o.m_StartLoop; s>>o.m_EndLoop; s>>o.m_Pos; s>>o.m_LastPos; s>>o.m_BarLength; s>>o.m_BeatsBar; int Num; s>>Num; float st,lt; int g,t; for (int n=0; n>st>>g>>lt>>t; o.AddEventTime(st,g,lt,(Fl_SEvent::Type)(t), false); } return s; } ostream &operator<<(ostream &s, Fl_EventMap &o) { s<<"EventMap "; s<<(int)o.m_Type<<" "; s<::iterator i=o.m_EventMap.begin(); i!=o.m_EventMap.end(); i++) { s<second->GetStartTime()<<" "<second->GetGroup()<<" "<< i->second->GetLengthTime()<<" "<<(int)(i->second->GetType())<<" "; } s<