You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

553 lines
12KB

  1. /* EventMap Widget
  2. * Copyleft (C) 2001 David Griffiths <dave@pawfal.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "Fl_EventMap.h"
  19. #include <FL/fl_draw.h>
  20. #include <FL/Fl_Window.h>
  21. #include <FL/x.H>
  22. #include <stdio.h>
  23. static const int AREA_WIDTH = 1000;
  24. static const int AREA_HEIGHT = 1000;
  25. static const int BUTTON_COLOUR = 10;
  26. static const int EVENT_COLOUR = 0;
  27. int BG_COLOUR;// = 139;
  28. int BLACK_KEY_COL;// = 141;
  29. int LINE_COLOUR;// = 140;
  30. ////////////////////////////////////////////////////////////////////
  31. Fl_EventMap::Fl_EventMap(int x, int y, int ww, int h, const char* label) :
  32. Fl_Group(x,y,ww,h,label),
  33. m_Type(ARRANGE_MAP),
  34. m_Update(true),
  35. m_Zoom(1.0f),
  36. m_GridSizeX(0),
  37. m_GridSizeY(10),
  38. m_PixelsPerSec(100),
  39. m_NextID(0),
  40. m_StartLoop(1.0f),
  41. m_EndLoop(2.0f),
  42. m_Pos(0),
  43. m_LastPos(0),
  44. m_DrawBeats(true),
  45. m_BarLength(1),
  46. m_BeatsBar(4),
  47. m_FirstUpdate(true)
  48. {
  49. box(FL_FLAT_BOX);
  50. fl_color(0,100,161);
  51. BG_COLOUR=fl_color();
  52. fl_color(0,90,150);
  53. BLACK_KEY_COL=fl_color();
  54. fl_color(0,80,150);
  55. LINE_COLOUR=fl_color();
  56. fl_color(200,200,200);
  57. // SpiralSound/Plugins/Widgets/Fl_EventMap.C:65: declaration of `w' shadows a parameter
  58. int w=fl_color();
  59. fl_color(50,50,50);
  60. int b=fl_color();
  61. // white/black keys for the melody
  62. m_KeyColMap[0] = w;
  63. m_KeyColMap[1] = b;
  64. m_KeyColMap[2] = w;
  65. m_KeyColMap[3] = b;
  66. m_KeyColMap[4] = w;
  67. m_KeyColMap[5] = w;
  68. m_KeyColMap[6] = b;
  69. m_KeyColMap[7] = w;
  70. m_KeyColMap[8] = b;
  71. m_KeyColMap[9] = w;
  72. m_KeyColMap[10] = b;
  73. m_KeyColMap[11] = w;
  74. }
  75. void Fl_EventMap::SetCallbacks(const EventCallbacks &s)
  76. {
  77. m_Callbacks.cb_NewEvent=s.cb_NewEvent;
  78. m_Callbacks.cb_EventDoubleClicked=s.cb_EventDoubleClicked;
  79. m_Callbacks.cb_CopyEvent=s.cb_CopyEvent;
  80. m_Callbacks.cb_CloneEvent=s.cb_CloneEvent;
  81. m_Callbacks.cb_InstanceEvent=s.cb_InstanceEvent;
  82. m_Callbacks.cb_MoveEvent=s.cb_MoveEvent;
  83. m_Callbacks.cb_EditEvent=s.cb_EditEvent;
  84. m_Callbacks.cb_DelEvent=s.cb_DelEvent;
  85. m_Callbacks.cb_RenameEvent=s.cb_RenameEvent;
  86. m_Callbacks.cb_Recolour=s.cb_Recolour;
  87. }
  88. void Fl_EventMap::CreateWindow()
  89. {
  90. show();
  91. }
  92. void Fl_EventMap::draw()
  93. {
  94. Fl_Widget*const* a = array();
  95. if (!(damage() & ~FL_DAMAGE_CHILD))
  96. {
  97. for (int i=children(); i--;) update_child(**a++);
  98. return;
  99. }
  100. draw_box();
  101. m_FirstUpdate=true;
  102. fl_color(BG_COLOUR);
  103. fl_rectf(x(),y(),w(),h());
  104. // draw the section markers
  105. if (m_GridSizeY)
  106. {
  107. int c=0;
  108. // draw the snap points
  109. for (int n=y(); n<y()+h(); n+=m_GridSizeY)
  110. {
  111. fl_color(LINE_COLOUR);
  112. fl_line(x(),n,x()+w(),n);
  113. // do black key bg
  114. if (m_Type==MELODY_MAP)
  115. {
  116. int cm = c%12;
  117. if (cm==1 || cm==3 || cm==6 || cm==8 || cm==10)
  118. {
  119. fl_color(BLACK_KEY_COL);
  120. fl_rectf(x(),n,w(),m_GridSizeY);
  121. }
  122. }
  123. c++;
  124. }
  125. }
  126. // draw the bar markers
  127. if (m_DrawBeats)
  128. {
  129. float BarLength=m_BarLength*(float)m_PixelsPerSec;
  130. float BeatLength=BarLength/(float)m_BeatsBar;
  131. float n=x();
  132. while (n<x()+w())
  133. {
  134. fl_color(LINE_COLOUR);
  135. fl_line((int)n,y(),(int)n,y()+h());
  136. if (m_Type==MELODY_MAP)
  137. {
  138. fl_line((int)n-1,y(),(int)n-1,y()+h());
  139. }
  140. if (m_Type!=ARRANGE_MAP)
  141. {
  142. // draw the beat markers
  143. float m=n;
  144. while(m<n+BarLength)
  145. {
  146. fl_color(LINE_COLOUR);
  147. fl_line((int)m,y(),(int)m,y()+h());
  148. m+=BeatLength;
  149. }
  150. }
  151. n+=BarLength;
  152. }
  153. }
  154. if (m_Type==ARRANGE_MAP)
  155. {
  156. fl_color(FL_BLACK);
  157. int StartPixels=(int)(m_StartLoop*(float)m_PixelsPerSec)+x();
  158. int EndPixels=(int)(m_EndLoop*(float)m_PixelsPerSec)+x();
  159. //fl_line(StartPixels,y()+15,StartPixels,y()+h());
  160. fl_line(EndPixels,y()+15,EndPixels,y()+h());
  161. }
  162. for (int i=children(); i--;) {
  163. Fl_Widget& o = **a++;
  164. draw_child(o);
  165. draw_outside_label(o);
  166. }
  167. SetFirstUpdate();
  168. }
  169. int Fl_EventMap::handle(int event)
  170. {
  171. if (!Fl_Group::handle(event) && event==FL_PUSH)
  172. {
  173. if (m_Type!=ARRANGE_MAP)
  174. {
  175. AddEvent(Fl::event_x(),Fl::event_y(),20, Fl_SEvent::NO_TYPE);
  176. }
  177. }
  178. for (map<int,Fl_SEvent*>::iterator i=m_EventMap.begin();
  179. i!=m_EventMap.end(); i++)
  180. {
  181. Fl_SEvent *pEvent = i->second;
  182. if (pEvent->Killed())
  183. {
  184. RemoveEvent(i->first);
  185. }
  186. }
  187. return event;
  188. }
  189. void Fl_EventMap::SetZoomLevel(float s)
  190. {
  191. m_Zoom=s;
  192. m_PixelsPerSec=int(100/m_Zoom);
  193. vector<EventInfo> EventVec;
  194. for (map<int,Fl_SEvent*>::iterator i=m_EventMap.begin();
  195. i!=m_EventMap.end(); i++)
  196. {
  197. i->second->SetPixelsPerSec(m_PixelsPerSec);
  198. }
  199. redraw();
  200. }
  201. void Fl_EventMap::SetSnapGap(float s)
  202. {
  203. m_GridSizeX=(int)(s*(float)m_PixelsPerSec);
  204. for (map<int,Fl_SEvent*>::iterator i=m_EventMap.begin();
  205. i!=m_EventMap.end(); i++)
  206. {
  207. i->second->SetSnapGap(s);
  208. }
  209. redraw();
  210. }
  211. void Fl_EventMap::SetTime(float Time)
  212. {
  213. assert(m_PixelsPerSec!=0);
  214. Time -= m_TimeOffset;
  215. m_Pos = (int)(Time*m_PixelsPerSec);
  216. // line marker update
  217. // all in all, some orrible code...
  218. if (m_Update && window()->visible() && visible_r() && m_Pos!=m_LastPos)
  219. {
  220. window()->make_current();
  221. int DrawPos=m_Pos+x();
  222. int Left=parent()->x();
  223. int Top=parent()->y();
  224. int Width=parent()->w();
  225. int Depth=parent()->h();
  226. if (DrawPos>Left && DrawPos<Left+Width)
  227. {
  228. #if !__APPLE__
  229. XSetFunction(fl_display,fl_gc,GXxor);
  230. XSetForeground(fl_display, fl_gc, 0xff00ffff);
  231. if (!m_FirstUpdate) fl_line(m_LastPos,Top,m_LastPos,Depth);
  232. fl_line(DrawPos,Top,DrawPos,Depth);
  233. XSetFunction(fl_display,fl_gc,GXcopy);
  234. #endif
  235. m_LastPos=DrawPos;
  236. }
  237. }
  238. m_FirstUpdate=false;
  239. }
  240. vector<EventInfo> Fl_EventMap::GetEvents(float Time)
  241. {
  242. SetTime(Time);
  243. vector<EventInfo> EventVec;
  244. for (map<int,Fl_SEvent*>::iterator i=m_EventMap.begin();
  245. i!=m_EventMap.end(); i++)
  246. {
  247. Fl_SEvent *pEvent = i->second;
  248. bool State=pEvent->UpdateState(Time);
  249. EventInfo::Type type=EventInfo::ON;
  250. if (pEvent->AtStart()) type=EventInfo::START;
  251. if (pEvent->AtEnd()) type=EventInfo::END;
  252. // Collect the events happening now, or just finished
  253. if(State || pEvent->AtEnd())
  254. {
  255. EventVec.push_back(EventInfo(pEvent->GetID(),pEvent->GetGroup(),
  256. type,pEvent->GetStartTime()));
  257. }
  258. }
  259. return EventVec;
  260. }
  261. int Fl_EventMap::GetGroupFromY(int y)
  262. {
  263. return y/m_GridSizeY;
  264. }
  265. int Fl_EventMap::AddEventTime(float st, int g, float lt, Fl_SEvent::Type EType, bool CallBack)
  266. {
  267. int ex,ey,ew;
  268. ex=(int)(st*(float)m_PixelsPerSec)+x();
  269. ew=(int)(lt*(float)m_PixelsPerSec);
  270. ey=g*m_GridSizeY+y();
  271. return AddEvent(ex, ey, ew, EType, CallBack);
  272. }
  273. int Fl_EventMap::AddEvent(int x, int y, int w, Fl_SEvent::Type EType, bool CallBack)
  274. {
  275. Fl_SEvent *NewEvent;
  276. if (m_Type==PERCUSSION_MAP)
  277. {
  278. NewEvent = new Fl_CircEvent(x,y,w,m_GridSizeY);
  279. }
  280. else
  281. {
  282. NewEvent = new Fl_SEvent(x,y,w,m_GridSizeY);
  283. }
  284. if (m_Type==MELODY_MAP) NewEvent->LockResize(false);
  285. NewEvent->SetPixelsPerSec(m_PixelsPerSec, true);
  286. NewEvent->color(EVENT_COLOUR);
  287. NewEvent->labelsize(10);
  288. NewEvent->SetID(m_NextID++);
  289. NewEvent->SetType(EType);
  290. char Name[256];
  291. if (m_Type==ARRANGE_MAP)
  292. {
  293. if(NewEvent->GetType()==Fl_SEvent::MELODY)
  294. sprintf(Name,"Melody %d",NewEvent->GetID());
  295. if(NewEvent->GetType()==Fl_SEvent::PERCUSSION)
  296. sprintf(Name,"Percussion %d",NewEvent->GetID());
  297. }
  298. else sprintf(Name,"This shouldnt be read!");
  299. NewEvent->SetName(Name);
  300. NewEvent->SetGridX(m_GridSizeX);
  301. NewEvent->SetGridY(m_GridSizeY);
  302. map<int,Fl_SEvent*>::iterator i=m_EventMap.find(NewEvent->GetID());
  303. if (i!=m_EventMap.end())
  304. {
  305. cerr<<"Event ID not unique, not added!"<<endl;
  306. delete NewEvent;
  307. return -1;
  308. }
  309. add(NewEvent);
  310. // can only build the menus after adding to the parent, as the features in the
  311. // menu depend on which callbacks have been filled out by the parent.
  312. NewEvent->BuildMenu();
  313. NewEvent->SnapX();
  314. NewEvent->SnapY();
  315. NewEvent->SetPixelsPerSec(m_PixelsPerSec,true);
  316. m_EventMap[NewEvent->GetID()]=NewEvent;
  317. int pID = NewEvent->GetID();
  318. if (m_Callbacks.cb_NewEvent && CallBack) m_Callbacks.cb_NewEvent(NewEvent,&pID);
  319. redraw();
  320. return NewEvent->GetID();
  321. }
  322. int Fl_EventMap::CopyEvent(int x, int y, int w, int ID, float LengthTime)
  323. {
  324. // make the new widget
  325. int NewID = AddEvent(x,y,w,m_EventMap[ID]->GetType(),false);
  326. // set the length of time exactly, as rounding
  327. // errors cause a reinit of the sample memory
  328. GetEvent(NewID)->SetLengthTime(LengthTime);
  329. //string Name="Copy of "+m_EventMap[ID]->GetName();
  330. //GetEvent(NewID)->SetName(Name);
  331. GetEvent(NewID)->SetName(m_EventMap[ID]->GetName());
  332. GetEvent(NewID)->SetColour(m_EventMap[ID]->GetColour());
  333. GetEvent(NewID)->SetChannel(m_EventMap[ID]->GetChannel());
  334. return NewID;
  335. }
  336. void Fl_EventMap::RemoveAllEvents()
  337. {
  338. for (map<int,Fl_SEvent*>::iterator i=m_EventMap.begin();
  339. i!=m_EventMap.end(); i++)
  340. {
  341. Fl_SEvent *e=i->second;
  342. remove(e);
  343. m_EventMap.erase(i);
  344. delete(e);
  345. }
  346. m_EventMap.clear();
  347. m_NextID=0;
  348. redraw();
  349. }
  350. void Fl_EventMap::RemoveEvent(int ID)
  351. {
  352. map<int,Fl_SEvent*>::iterator i=m_EventMap.find(ID);
  353. if (i==m_EventMap.end())
  354. {
  355. cerr<<"Event ID not found to delete"<<endl;
  356. return;
  357. }
  358. Fl_SEvent *e=i->second;
  359. remove(e);
  360. m_EventMap.erase(i);
  361. delete(e);
  362. cerr<<"removed "<<ID<<endl;
  363. }
  364. Fl_SEvent *Fl_EventMap::GetEvent(int ID)
  365. {
  366. map<int,Fl_SEvent*>::iterator i=m_EventMap.find(ID);
  367. if (i==m_EventMap.end())
  368. {
  369. cerr<<"Event ID not found"<<endl;
  370. return NULL;
  371. }
  372. return m_EventMap[ID];
  373. }
  374. void Fl_EventMap::SetEventLength(int ID, float l)
  375. {
  376. Fl_SEvent *e=GetEvent(ID);
  377. if(e) e->SetLengthTime(l);
  378. }
  379. void Fl_EventMap::CopyFrom(Fl_EventMap *Other)
  380. {
  381. m_Type = Other->m_Type;
  382. m_Zoom = Other->m_Zoom;
  383. m_GridSizeX = Other->m_GridSizeX;
  384. m_GridSizeY = Other->m_GridSizeY;
  385. m_PixelsPerSec = Other->m_PixelsPerSec;
  386. m_StartLoop = Other->m_StartLoop;
  387. m_EndLoop = Other->m_EndLoop;
  388. m_Pos = Other->m_Pos;
  389. m_LastPos = Other->m_LastPos;
  390. m_BarLength = Other->m_BarLength;
  391. m_BeatsBar = Other->m_BeatsBar;
  392. m_NextID = Other->m_NextID;
  393. for (map<int,Fl_SEvent*>::iterator i=Other->m_EventMap.begin();
  394. i!=Other->m_EventMap.end(); i++)
  395. {
  396. Fl_SEvent *NewEvent;
  397. if (m_Type==PERCUSSION_MAP)
  398. {
  399. NewEvent = new Fl_CircEvent(*(Fl_CircEvent*)i->second);
  400. }
  401. else
  402. {
  403. NewEvent = new Fl_SEvent(*i->second);
  404. }
  405. add(NewEvent);
  406. m_EventMap[NewEvent->GetID()]=NewEvent;
  407. }
  408. }
  409. /////////////////////////////////////////////////////
  410. istream &operator>>(istream &s, Fl_EventMap &o)
  411. {
  412. string dummy;
  413. s>>dummy;
  414. if (dummy!="EventMap") cerr<<"Error in stream before Fl_EventMap"<<endl;
  415. s>>(int&)o.m_Type;
  416. s>>o.m_Zoom;
  417. s>>o.m_GridSizeX;
  418. s>>o.m_GridSizeY;
  419. s>>o.m_PixelsPerSec;
  420. s>>o.m_StartLoop;
  421. s>>o.m_EndLoop;
  422. s>>o.m_Pos;
  423. s>>o.m_LastPos;
  424. s>>o.m_BarLength;
  425. s>>o.m_BeatsBar;
  426. int Num;
  427. s>>Num;
  428. float st,lt;
  429. int g,t;
  430. for (int n=0; n<Num; n++)
  431. {
  432. s>>st>>g>>lt>>t;
  433. o.AddEventTime(st,g,lt,(Fl_SEvent::Type)(t), false);
  434. }
  435. return s;
  436. }
  437. ostream &operator<<(ostream &s, Fl_EventMap &o)
  438. {
  439. s<<"EventMap ";
  440. s<<(int)o.m_Type<<" ";
  441. s<<o.m_Zoom<<" ";
  442. s<<o.m_GridSizeX<<" ";
  443. s<<o.m_GridSizeY<<" ";
  444. s<<o.m_PixelsPerSec<<" ";
  445. s<<o.m_StartLoop<<" ";
  446. s<<o.m_EndLoop<<" ";
  447. s<<o.m_Pos<<" ";
  448. s<<o.m_LastPos<<" ";
  449. s<<o.m_BarLength<<" ";
  450. s<<o.m_BeatsBar<<" ";
  451. s<<o.m_EventMap.size()<<" ";
  452. for (map<int,Fl_SEvent*>::iterator i=o.m_EventMap.begin();
  453. i!=o.m_EventMap.end(); i++)
  454. {
  455. s<<i->second->GetStartTime()<<" "<<i->second->GetGroup()<<" "<<
  456. i->second->GetLengthTime()<<" "<<(int)(i->second->GetType())<<" ";
  457. }
  458. s<<endl;
  459. return s;
  460. }