Merge branch 'master' of https://scm.cri.ensmp.fr/git/Faustine
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / draw / schema / blockSchema.cpp
1 /************************************************************************
2 ************************************************************************
3 FAUST compiler
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
21
22
23 #include "blockSchema.h"
24 #include <assert.h>
25
26 using namespace std;
27
28 static double quantize(int n)
29 {
30 int q = 3;
31 return dLetter * (q *((n+q-1)/q));
32 }
33
34 /**
35 * Build a simple colored blockSchema with a certain number of
36 * inputs and outputs, a text to be displayed, and an optional link.
37 * Computes the size of the box according to the length of the text
38 * and the maximum number of ports.
39 */
40 schema* makeBlockSchema ( unsigned int inputs,
41 unsigned int outputs,
42 const string& text,
43 const string& color,
44 const string& link )
45 {
46 // determine the optimal size of the box
47 double minimal = 3*dWire;
48 double w = 2*dHorz + max( minimal, quantize(text.size()) );
49 double h = 2*dVert + max( minimal, max(inputs, outputs) * dWire );
50
51 return new blockSchema(inputs, outputs, w, h, text, color, link);
52 }
53
54 /**
55 * Build a simple colored blockSchema with a certain number of
56 * inputs and outputs, a text to be displayed, and an optional link.
57 * The length of the text as well as th number of inputs and outputs
58 * are used to compute the size of the blockSchema
59 */
60 blockSchema::blockSchema ( unsigned int inputs,
61 unsigned int outputs,
62 double width,
63 double height,
64 const string& text,
65 const string& color,
66 const string& link )
67
68 : schema( inputs, outputs, width, height ),
69 fText(text),
70 fColor(color),
71 fLink(link)
72 {
73 for (unsigned int i=0; i<inputs; i++) fInputPoint.push_back(point(0,0));
74 for (unsigned int i=0; i<outputs; i++) fOutputPoint.push_back(point(0,0));
75 }
76
77 /**
78 * Define the graphic position of the blockSchema. Computes the graphic
79 * position of all the elements, in particular the inputs and outputs.
80 * This method must be called before draw(), otherwise draw is not allowed
81 */
82 void blockSchema::place(double x, double y, int orientation)
83 {
84 beginPlace(x, y, orientation);
85
86 placeInputPoints();
87 placeOutputPoints();
88
89 endPlace();
90 }
91
92 /**
93 * Returns an input point
94 */
95 point blockSchema::inputPoint(unsigned int i) const
96 {
97 assert (placed());
98 assert (i < inputs());
99 return fInputPoint[i];
100 }
101
102 /**
103 * Returns an output point
104 */
105 point blockSchema::outputPoint(unsigned int i) const
106 {
107 assert (placed());
108 assert (i < outputs());
109 return fOutputPoint[i];
110 }
111
112 /**
113 * Computes the input points according to the position and the
114 * orientation of the blockSchema
115 */
116 void blockSchema::placeInputPoints()
117 {
118 int N = inputs();
119
120 if (orientation() == kLeftRight) {
121
122 double px = x();
123 double py = y() + (height() - dWire*(N-1))/2;
124
125 for (int i=0; i<N; i++) {
126 fInputPoint[i] = point(px, py+i*dWire);
127 }
128
129 } else {
130
131 double px = x() + width();
132 double py = y() + height() - (height() - dWire*(N-1))/2;
133
134 for (int i=0; i<N; i++) {
135 fInputPoint[i] = point(px, py-i*dWire);
136 }
137 }
138 }
139
140
141 /**
142 * Computes the output points according to the position and the
143 * orientation of the blockSchema
144 */
145 void blockSchema::placeOutputPoints()
146 {
147 int N = outputs();
148
149 if (orientation() == kLeftRight) {
150
151 double px = x() + width();
152 double py = y() + (height() - dWire*(N-1))/2;
153
154 for (int i=0; i<N; i++) {
155 fOutputPoint[i] = point(px, py + i*dWire);
156 }
157
158 } else {
159
160 double px = x();
161 double py = y() + height() - (height() - dWire*(N-1))/2;
162
163 for (int i=0; i<N; i++) {
164 fOutputPoint[i] = point(px, py - i*dWire);
165 }
166 }
167 }
168
169
170 /**
171 * Draw the blockSchema on the device. This methos can only
172 * be called after the blockSchema have been placed
173 */
174 void blockSchema::draw(device& dev)
175 {
176 assert(placed());
177
178 drawRectangle(dev);
179 drawText(dev);
180 drawOrientationMark(dev);
181 drawInputWires(dev);
182 drawOutputWires(dev);
183 }
184
185 /**
186 * Draw the colored rectangle with the optional link
187 */
188 void blockSchema::drawRectangle(device& dev)
189 {
190 dev.rect( x() + dHorz,
191 y() + dVert,
192 width() - 2*dHorz,
193 height() - 2*dVert,
194 fColor.c_str(),
195 fLink.c_str()
196 );
197 }
198
199
200 /**
201 * Draw the text centered on the box
202 */
203 void blockSchema::drawText(device& dev)
204 {
205 dev.text( x() + width()/2,
206 y() + height()/2,
207 fText.c_str(),
208 fLink.c_str()
209 );
210 }
211
212
213 /**
214 * Draw the orientation mark, a small point that indicates
215 * the first input (like integrated circuits)
216 */
217 void blockSchema::drawOrientationMark(device& dev)
218 {
219 double px, py;
220
221 if (orientation() == kLeftRight) {
222 px = x() + dHorz;
223 py = y() + dVert;
224 } else {
225 px = x() + width() - dHorz;
226 py = y() + height() - dVert;
227 }
228
229 dev.markSens( px, py, orientation() );
230 }
231 #if 1
232 /**
233 * Draw horizontal arrows from the input points to the
234 * blockSchema rectangle
235 */
236 void blockSchema::drawInputWires(device& dev)
237 {
238 double dx = (orientation() == kLeftRight) ? dHorz : -dHorz;
239
240 for (unsigned int i=0; i<inputs(); i++) {
241 point p = fInputPoint[i];
242 //dev.trait(p.x, p.y, p.x+dx, p.y);
243 dev.fleche(p.x+dx, p.y, 0, orientation());
244 }
245 }
246
247 /**
248 * Draw horizontal line from the blockSchema rectangle to the
249 * output points
250 */
251 void blockSchema::drawOutputWires(device& dev)
252 {
253 //double dx = (orientation() == kLeftRight) ? dHorz : -dHorz;
254
255 for (unsigned int i=0; i<outputs(); i++) {
256 point p = fOutputPoint[i];
257 //dev.trait(p.x, p.y, p.x-dx, p.y);
258 }
259 }
260 #endif
261
262 /**
263 * Draw horizontal arrows from the input points to the
264 * blockSchema rectangle
265 */
266 void blockSchema::collectTraits(collector& c)
267 {
268 collectInputWires(c);
269 collectOutputWires(c);
270 }
271
272 /**
273 * Draw horizontal arrows from the input points to the
274 * blockSchema rectangle
275 */
276 void blockSchema::collectInputWires(collector& c)
277 {
278 double dx = (orientation() == kLeftRight) ? dHorz : -dHorz;
279
280 for (unsigned int i=0; i<inputs(); i++) {
281 point p = fInputPoint[i];
282 c.addTrait(trait(point(p.x, p.y), point(p.x+dx, p.y))); // in->out direction
283 c.addInput(point(p.x+dx, p.y));
284 }
285 }
286
287 /**
288 * Draw horizontal line from the blockSchema rectangle to the
289 * output points
290 */
291 void blockSchema::collectOutputWires(collector& c)
292 {
293 double dx = (orientation() == kLeftRight) ? dHorz : -dHorz;
294
295 for (unsigned int i=0; i<outputs(); i++) {
296 point p = fOutputPoint[i];
297 c.addTrait(trait(point(p.x-dx, p.y), point(p.x, p.y))); // in->out direction
298 c.addOutput(point(p.x-dx, p.y));
299 }
300 }
301
302