]> git.lyx.org Git - lyx.git/blob - src/mathed/math_matrixinset.C
small cleanup, doxygen, formatting changes
[lyx.git] / src / mathed / math_matrixinset.C
1 #include <config.h>
2
3 #include "math_matrixinset.h"
4 #include "math_rowst.h"
5 #include "math_xiter.h"
6 #include "support/LOstream.h"
7
8 using std::ostream;
9
10 extern int number_of_newlines;
11
12 MathMatrixInset::MathMatrixInset(int m, int n, short st)
13         : MathParInset(st, "array", LM_OT_MATRIX), nc_(m), nr_(0), ws_(m),
14           v_align_(0), h_align_(nc_, 'c'), row_(0)
15 {
16         flag = 15;
17         if (n > 0) {
18                 row_ = new MathedRowSt(nc_ + 1);
19                 MathedXIter it(this);
20                 for (int j = 1; j < n; ++j) it.addRow();
21                 nr_ = n;
22                 if (nr_ == 1 && nc_ > 1) {
23                         for (int j = 0; j < nc_ - 1; ++j) 
24                                 it.Insert('T', LM_TC_TAB);
25                 }
26         } else if (n < 0) {
27                 row_ = new MathedRowSt(nc_ + 1);
28                 nr_ = 1;
29         }
30 }
31
32
33 MathMatrixInset::MathMatrixInset(MathMatrixInset * mt)
34         : MathParInset(mt->GetStyle(), mt->GetName(), mt->GetType()),
35           nc_(mt->nc_), nr_(0), ws_(mt->nc_),
36           v_align_(mt->v_align_), h_align_(mt->h_align_)
37 {
38         MathedIter it;
39         it.SetData(mt->GetData());
40         array = it.Copy();
41         if (mt->row_ != 0) {
42                 MathedRowSt * ro = 0;
43                 MathedRowSt * mrow = mt->row_;
44
45                 while (mrow) {
46                         MathedRowSt * r = new MathedRowSt(nc_ + 1);
47                         r->setNumbered(mrow->isNumbered());
48                         //if (mrow->label) 
49                         r->setLabel(mrow->getLabel());
50                         if (!ro) 
51                                 row_ = r;
52                         else
53                                 ro->setNext(r);
54                         mrow = mrow->getNext();
55                         ro = r;
56                         ++nr_;
57                 }
58         } else   
59                 row_ = 0;
60         flag = mt->flag;
61 }
62
63
64 MathMatrixInset::~MathMatrixInset()
65 {
66         MathedRowSt * r = row_;
67         while (r) {
68                 MathedRowSt * q = r->getNext();
69                 delete r;
70                 r = q;
71         }
72 }
73
74
75 MathedInset * MathMatrixInset::Clone()
76 {
77         return new MathMatrixInset(this);
78 }
79
80
81 void MathMatrixInset::SetAlign(char vv, string const & hh)
82 {
83         v_align_ = vv;
84         h_align_ = hh.substr(0, nc_); // usr just h_align = hh; perhaps
85 }
86
87
88 // Check the number of tabs and crs
89 void MathMatrixInset::setData(MathedArray * a)
90 {
91         if (!a) return;
92         MathedIter it(a);
93         int nn = nc_ - 1;
94         nr_ = 1;
95         // count tabs per row
96         while (it.OK()) {
97                 if (it.IsTab()) {
98                         if (nn < 0) { 
99                                 it.Delete();
100                                 continue;
101                         } else {
102                                 // it.Next();
103                                 --nn;
104                         }
105                 }
106                 if (it.IsCR()) {
107                         while (nn > 0) {
108                                 it.Insert(' ', LM_TC_TAB);
109                                 --nn;
110                         }
111                         nn = nc_ - 1;
112                         ++nr_;
113                 }
114                 it.Next();
115         }
116         it.Reset();
117         
118         // Automatically inserts tabs around bops
119         // DISABLED because it's very easy to insert tabs 
120         array = a;
121 }
122
123
124 void MathMatrixInset::draw(Painter & pain, int x, int baseline)
125 {
126         MathParInset::draw(pain, x, baseline);
127 }
128
129
130
131 void MathMatrixInset::Metrics()
132 {
133         if (!row_) {
134                 // lyxerr << " MIDA ";
135                 MathedXIter it(this);
136                 row_ = it.adjustVerticalSt();
137         } 
138         
139         // Clean the arrays      
140         MathedRowSt * cxrow = row_;
141         while (cxrow) {   
142                 for (int i = 0; i <= nc_; ++i)
143                         cxrow->setTab(i, 0);
144                 cxrow = cxrow->getNext();
145         }
146         
147         // Basic metrics
148         MathParInset::Metrics();
149         
150         if (nc_ <= 1 && !row_->getNext()) {
151                 row_->ascent(ascent);
152                 row_->descent(descent);
153         }
154         
155         // Vertical positions of each row
156         cxrow = row_;     
157         MathedRowSt * cprow = 0;
158         int h = 0;
159         while (cxrow) {
160                 for (int i = 0; i < nc_; ++i) {
161                         if (cxrow == row_ || ws_[i] < cxrow->getTab(i))
162                                 ws_[i] = cxrow->getTab(i);
163                         if (cxrow->getNext() == 0 && ws_[i] == 0)
164                                 ws_[i] = df_width;
165                 }
166                 
167                 cxrow->setBaseline((cxrow == row_) ?
168                                    cxrow->ascent() :
169                                    cxrow->ascent() + cprow->descent()
170                                    + MATH_ROWSEP + cprow->getBaseline());
171                 h += cxrow->ascent() + cxrow->descent() + MATH_ROWSEP;  
172                 cprow = cxrow;
173                 cxrow = cxrow->getNext();
174         }
175         
176         int hl = Descent();
177         h -= MATH_ROWSEP;
178         
179         //  Compute vertical align
180         switch (v_align_) {
181         case 't':
182                 ascent = row_->getBaseline();
183                 break;
184         case 'b':
185                 ascent = h - hl;
186                 break;
187         default:
188                 ascent = (row_->getNext()) ? h / 2 : h - hl;
189                 break;
190         }
191         descent = h - ascent + 2;
192         
193         // Increase ws_[i] for 'R' columns (except the first one)
194         for (int i = 1; i < nc_; ++i)
195                 if (h_align_[i] == 'R')
196                         ws_[i] += 10 * df_width;
197         // Increase ws_[i] for 'C' column
198         if (h_align_[0] == 'C')
199                 if (ws_[0] < 7 * workWidth / 8)
200                         ws_[0] = 7 * workWidth / 8;
201         
202         // Adjust local tabs
203         cxrow = row_;
204         width = MATH_COLSEP;
205         while (cxrow) {   
206                 int rg = MATH_COLSEP;
207                 int lf = 0;
208                 for (int i = 0; i < nc_; ++i) {
209                         bool isvoid = false;
210                         if (cxrow->getTab(i) <= 0) {
211                                 cxrow->setTab(i, df_width);
212                                 isvoid = true;
213                         }
214                         switch (h_align_[i]) {
215                         case 'l':
216                                 lf = 0;
217                                 break;
218                         case 'c':
219                                 lf = (ws_[i] - cxrow->getTab(i))/2; 
220                                 break;
221                         case 'r':
222                         case 'R':
223                                 lf = ws_[i] - cxrow->getTab(i);
224                                 break;
225                         case 'C':
226                                 if (cxrow == row_)
227                                         lf = 0;
228                                 else if (!cxrow->getNext())
229                                         lf = ws_[i] - cxrow->getTab(i);
230                                 else
231                                         lf = (ws_[i] - cxrow->getTab(i))/2; 
232                                 break;
233                         }
234                         int ww = (isvoid) ? lf : lf + cxrow->getTab(i);
235                         cxrow->setTab(i, lf + rg);
236                         rg = ws_[i] - ww + MATH_COLSEP;
237                         if (cxrow == row_)
238                                 width += ws_[i] + MATH_COLSEP;
239                 }
240                 cxrow->setBaseline(cxrow->getBaseline() - ascent);
241                 cxrow = cxrow->getNext();
242         }
243 }
244
245
246 void MathMatrixInset::Write(ostream & os, bool fragile)
247 {
248         if (GetType() == LM_OT_MATRIX) {
249                 if (fragile)
250                         os << "\\protect";
251                 os << "\\begin{"
252                    << name
253                    << '}';
254                 if (v_align_ == 't' || v_align_ == 'b') {
255                         os << '['
256                            << char(v_align_)
257                            << ']';
258                 }
259                 os << '{'
260                    << h_align_
261                    << "}\n";
262                 ++number_of_newlines;
263         }
264         MathParInset::Write(os, fragile);
265         if (GetType() == LM_OT_MATRIX){
266                 os << "\n";
267                 if (fragile)
268                         os << "\\protect";
269                 os << "\\end{"
270                    << name
271                    << '}';
272                 ++number_of_newlines;
273         }
274 }