//=========================================================
//  MusE
//  Linux Music Editor
//    $Id: layout.h,v 1.1.1.1 2003/10/29 10:05:29 wschweer Exp $
//  (C) Copyright 1999,2000 Werner Schweer (ws@seh.de)
//=========================================================

#ifndef __LAYOUT_H__
#define __LAYOUT_H__

#include <list>

#include "ncanvas.h"
#include "track.h"
#include "key.h"

#define DPMM   (72.0/25.4)    // Postscript Units
#define mm2dot(x) int((x)*72.0/25.4/printScale)

class MidiTrack;
class QRect;
class QPainter;
class QPainter;
class ScoreCanvas;

//
// ScoreList item
//
//      iPage-PageList
//          iSystem-SystemList
//                iStaveRow-StaveRowList
//                      iScore-ScoreList
//


enum SplitMode { NOSPLIT, UPPER, LOWER};

//---------------------------------------------------------
//   Stave
//---------------------------------------------------------

struct Stave {
      MidiTrack* track;
      SplitMode mode;
      Scale scale;      // copy from track
      NKey key;         // copy from track
      int nq, rq;       // note quant, rest quant; copy from track
      int cnq, crq;     // current note quant, rest quant
      int lines;        // typically there are 5 lines

      Stave(MidiTrack* t, SplitMode m, int);
      };

typedef std::list<Stave> StaveList;
typedef StaveList::iterator iStave;

struct System;

//---------------------------------------------------------
//   StaveRow
//---------------------------------------------------------

struct StaveRow {
      System* system;         // backlink to system
      Stave*  stave;
      ScoreList items;
      QPoint offset;
      int no;

   public:
      StaveRow(System* sy, Stave* st, const QPoint& of, int n)
         : system(sy), stave(st), offset(of), no(n) {}

      void add(ScoreItem* item) {
            item->setStaveRow(this);
            item->setOffset(offset);
            items.add(item);
            }
      StaveRow* next() const;
      };

typedef std::list<StaveRow> StaveRowList;
typedef StaveRowList::iterator iStaveRow;
typedef StaveRowList::const_iterator ciStaveRow;

//---------------------------------------------------------
//   System
//---------------------------------------------------------

class Page;
struct System {
      Page* page;             // backlink to page
      StaveRowList staves;
      int startBar, endBar;
      int startTick, endTick;
      int xoffset;         // left offset to first tick-position
      int measureWidth;    // measure Width in pixel
      };

typedef std::list<System> SystemList;
typedef SystemList::iterator iSystem;
typedef SystemList::const_iterator ciSystem;

//---------------------------------------------------------
//   Page
//---------------------------------------------------------

struct Page {
      ScoreList items;        // layout items
      SystemList systems;
      int startBar, endBar;
      int pageno;
      };

typedef std::list<Page> PageList;
typedef PageList::iterator iPage;
typedef PageList::const_iterator ciPage;

//---------------------------------------------------------
//   SystemLayout
//---------------------------------------------------------

class SystemLayout {
      TrackList _tracks;

      StaveList staves;
      PageList pages;
      Page* curPage;

      // Layout Defaults:
      int measuresSystem;  // default measures per system
      int lines;           // default number of lines per stave
      int topOffset;       // top distance to first stave
      int lineD;           // line distance
      int keyOffset;       // distance left margin to key
      int lineWidth;
      int titleHeight;
      int systemSep;       // extra distance between Systems
      int staveSep;        // distance between Staves

      // collect items
      int startBar, endBar;   // range of Layout

      // tmp values:
      char tversatz[128];     // temp. Versetzungszeichen per Takt
      int curBar;
      int ticksBar;
      int stick;              // first tick value on system
      int sbtick;             // first tick on current bar
      int ctick;              // tick of current bar
      int sbx;                // x-position of current bar
      int xoffset;
      int measureWidth;
      Stave* stave;           // current stave

      void constructPage();
      void constructSystem(System*);
      void constructStaveRow(StaveRow*);
      void insertRest(StaveRow*, int tick, int len);
      int tick2len(int tick) const;
      int tick2xy(int tick, MidiEvent* ev, int& xx, int& y, int& prefix);
      void split(NoteItem* item, int t);
      int setNote(int tick, NoteItem* item);
      void print(FILE* f);

   public:
      int bracketWidth;
      int lineHeight;
      int lineHeight1;        // distance in split system

      SystemLayout();
      void updateTracks(std::list<int>&);
      void layout1();
      void layout2();
      void draw(QPainter& p, const QRect& r);
      void print();
      void preview();
      int getPages() const;
      void setPage(int n);
      ScoreItem* searchItem(const QPoint& p) const;
      NoteItem* searchItem(const MidiEvent*) const;
      bool searchItem(const ScoreItem*, iScore&, ScoreList*&) const;
      bool searchItem(const StaveRow*, iStaveRow&, StaveRowList*&) const;
      bool searchItem(const System*, iSystem&, SystemList*&) const;
      Page* page() const { return curPage; }
      void move(ScoreItem*, const QPoint&);
      int y2pitch(int y) const;
      int xy2tick(const QPoint&, int* ry=0, StaveRow** sr=0) const;
      int xy2tick(const QPoint&, int* ry, StaveRow* sr) const;
      bool tick2pos(int tick, int*, int*, int*);
      void collect(ScoreList*, MidiEvent*);
      void printLayout() const;
      TrackList* tracks() { return &_tracks; }
      void updateSelection(ScoreCanvas* scoreCanvas);
      };
#endif

