]> AND Private Git Repository - blast.git/blob - AbstractBoxItem.cpp
Logo AND Algorithmique Numérique Distribuée

Private GIT Repository
b76bf667b798e2190e7c9af53a0ffd596758fa18
[blast.git] / AbstractBoxItem.cpp
1 #include "AbstractBoxItem.h"
2
3 #include "Parameters.h"
4
5 #include "Dispatcher.h"
6 #include "InterfaceItem.h"
7 #include "ConnectionItem.h"
8
9 #include "AbstractBlock.h"
10 #include "GroupScene.h"
11 #include "GroupItem.h"
12 #include "AbstractInterface.h"
13 #include "ConnectedInterface.h"
14
15
16 AbstractBoxItem::  AbstractBoxItem(AbstractBlock *_refBlock, Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem *parent) : QGraphicsItem(parent) {
17   dispatcher = _dispatcher;
18   params = _params;
19   refBlock = _refBlock;  
20   QFontMetrics fmId(params->defaultBlockFont);
21   nameWidth = fmId.width(refBlock->getName());
22   nameHeight = fmId.height();
23   nameMargin = 10;
24   ifaceMargin = 10;
25
26   // the six following values will be override in subclass constructors
27   minimumBoxWidth = 0;
28   minimumBoxHeight = 0;
29   boxWidth = 0;
30   boxHeight = 0;
31   totalWidth = 0;
32   totalHeight = 0;
33
34   originPoint = QPointF(0.0,0.0);
35
36   selected = false;
37   currentInterface = NULL;
38   rstClkVisible = false;
39   wishboneVisible = false;
40
41   setAcceptHoverEvents(true);
42
43   // NOTE : initInterfaces() is only called in subclasses
44 }
45
46 AbstractBoxItem::AbstractBoxItem(Dispatcher *_dispatcher, Parameters *_params, QGraphicsItem* parent) : QGraphicsItem(parent) {
47   dispatcher = _dispatcher;
48   params = _params;
49   refBlock = NULL;
50   nameWidth = 0;
51   nameHeight = 0;
52   nameMargin = 10;
53   ifaceMargin = 10;
54
55   // the six following values will be override in subclass constructors
56   minimumBoxWidth = 0;
57   minimumBoxHeight = 0;
58   boxWidth = 0;
59   boxHeight = 0;
60   totalWidth = 0;
61   totalHeight = 0;
62
63   originPoint = QPointF(0.0,0.0);
64
65   selected = false;
66   currentInterface = NULL;
67   rstClkVisible = false;
68   wishboneVisible = false;
69   
70   setAcceptHoverEvents(true);
71
72   // NOTE : initInterfaces() is only called in subclasses
73 }
74
75 AbstractBoxItem::~AbstractBoxItem() {
76   foreach(InterfaceItem* inter, interfaces) {
77     delete inter;
78   }
79   interfaces.clear();
80 }
81
82 bool AbstractBoxItem::isBoxItem() {
83   return false;
84 }
85
86 bool AbstractBoxItem::isGroupItem() {
87   return false;
88 }
89 void AbstractBoxItem::setRstClkVisible(bool b) { 
90   rstClkVisible = b;
91   foreach(InterfaceItem* ifaceItem, interfaces) {
92     if ((ifaceItem->refInter->getPurpose() == AbstractInterface::Clock) ||
93         (ifaceItem->refInter->getPurpose() == AbstractInterface::Reset) ) {
94       ifaceItem->visible = b;
95     }
96   }
97   resetInterfacesPosition();
98   updateGeometry(InterfaceMove);
99   update();
100   getScene()->updateConnectionItemsShape();
101   (getScene()->getGroupItem())->updateShape();
102   
103 }
104
105 void AbstractBoxItem::setWishboneVisible(bool b) { 
106   wishboneVisible = b;
107   foreach(InterfaceItem* ifaceItem, interfaces) {
108     if (ifaceItem->refInter->getPurpose() == AbstractInterface::Wishbone) {
109       ifaceItem->visible = b;
110     }
111   }
112   resetInterfacesPosition();
113   updateGeometry(InterfaceMove);
114   update();
115   getScene()->updateConnectionItemsShape();
116   (getScene()->getGroupItem())->updateShape();
117 }
118
119 void AbstractBoxItem::setRefBlock(AbstractBlock* _refBlock) {
120   refBlock = _refBlock;
121   QFontMetrics fmId(params->defaultBlockFont);
122   nameWidth = fmId.width(refBlock->getName());
123   nameHeight = fmId.height();
124 }
125
126 void AbstractBoxItem::initInterfaces() {
127   /* TO DO : creating all needed InterfaceItem, with by default, input at west and output at east */
128   int orientation = Parameters::West;
129
130   foreach(AbstractInterface *inter, refBlock->getInterfaces()){
131    
132     /* NB: create InterfaceItem for every interfaces, even if they do not have a graphical representation
133        It will allow to save them in the XML project file and thus to create their equivalent
134        in the graph while the file is loaded.      
135     */
136     InterfaceItem *item;
137     if(inter->getDirection() == AbstractInterface::Input){
138       orientation = Parameters::West;
139     } else if(inter->getDirection() == AbstractInterface::Output){
140       orientation = Parameters::East;
141     } else if(inter->getDirection() == AbstractInterface::InOut){
142       orientation = Parameters::North;
143     }
144     item = new InterfaceItem(0.0 , orientation, (ConnectedInterface *)inter, this, params);
145     interfaces.append(item);        
146   }
147 }
148
149 InterfaceItem* AbstractBoxItem::searchInterfaceByName(QString name) {
150   foreach(InterfaceItem *inter, interfaces){
151     if(inter->getName() == name)
152       return inter;
153   }
154   return NULL;
155 }
156
157 InterfaceItem* AbstractBoxItem::searchInterfaceByRef(ConnectedInterface *ref) {
158   foreach(InterfaceItem *inter, interfaces){
159     if(inter->refInter == ref) {
160       return inter;
161     }
162   }
163   return NULL;
164 }
165
166 void AbstractBoxItem::addInterface(InterfaceItem *i, bool resetPosition) {
167   interfaces.append(i);
168   if (resetPosition) resetInterfacesPosition();
169   updateGeometry(InterfaceMove);
170   update();
171 }
172
173 void AbstractBoxItem::removeInterface(InterfaceItem *i) {
174   // NB : removing from model is done in dispatcher
175   interfaces.removeOne(i);
176   delete i;
177
178   //resetInterfacesPosition();
179   updateGeometry(InterfaceMove);
180   update();
181 }
182
183
184 void AbstractBoxItem::resetInterfacesPosition() {
185
186   int nbNorth=0, nbSouth=0, nbEast=0, nbWest=0;
187   double cntNorth=1.0,cntSouth=1.0,cntEast=1.0,cntWest=1.0;
188   double positionRatio = 1.0;
189
190
191   foreach(InterfaceItem* inter, interfaces) {
192     // only data interfaces and if needed time and reset
193     if(inter->visible) {
194       if(inter->getOrientation() == Parameters::North){
195         nbNorth++;
196       } else if(inter->getOrientation() == Parameters::South){
197         nbSouth++;
198       } else if(inter->getOrientation() == Parameters::East){
199         nbEast++;
200       } else if(inter->getOrientation() == Parameters::West){
201         nbWest++;
202       }
203     }
204   }
205
206   foreach(InterfaceItem* inter, interfaces) {
207
208     if(inter->visible){
209
210       if(inter->getOrientation() == Parameters::North){
211         positionRatio = cntNorth/(double)(nbNorth+1);
212         cntNorth += 1.0;
213       } else if(inter->getOrientation() == Parameters::South){
214         positionRatio = cntSouth/(double)(nbSouth+1);
215         cntSouth += 1.0;
216       } else if(inter->getOrientation() == Parameters::East){
217         positionRatio = cntEast/(double)(nbEast+1);
218         cntEast += 1.0;
219       } else if(inter->getOrientation() == Parameters::West){
220         positionRatio = cntWest/(double)(nbWest+1);
221         cntWest += 1.0;
222       }
223       inter->setPositionRatio(positionRatio);
224       inter->updatePosition();
225     }
226   }
227 }
228
229 void AbstractBoxItem::moveInterfaceTo(QPointF pos) {
230   double positionRatio;
231   if(currentInterface->getOrientation() == Parameters::North || currentInterface->getOrientation() == Parameters::South){
232     if(pos.x() < 0){
233       positionRatio = 0;
234       if(pos.y() > 0 && pos.y() < boxHeight){
235         currentInterface->setOrientation(Parameters::West);
236       }
237     } else if(pos.x() > boxWidth){
238       positionRatio = 1;
239       if(pos.y() > 0 && pos.y() < boxHeight){
240         currentInterface->setOrientation(Parameters::East);
241       }
242     } else {
243       positionRatio = ((double) pos.x())/boxWidth;
244     }
245   } else {
246
247     if(pos.y() < 0){
248       positionRatio = 0;
249       if(pos.x() > 0 && pos.x() < boxWidth){
250         currentInterface->setOrientation(Parameters::North);
251       }
252     } else if(pos.y() > boxHeight){
253       positionRatio = 1;
254       if(pos.x() > 0 && pos.x() < boxWidth){
255         currentInterface->setOrientation(Parameters::South);
256       }
257     } else {
258       positionRatio = ((double) pos.y())/boxHeight;
259     }
260   }
261   currentInterface->setPositionRatio(positionRatio);
262   currentInterface->updatePosition();
263 }
264
265 QRectF AbstractBoxItem::boundingRect() const {
266   // returns a QRectF that contains the block (i.e the main rectangle, interfaces, title, ...)
267   QPointF p = originPoint - QPointF(nameHeight,nameHeight);
268   QSizeF s(totalWidth+2*nameHeight,totalHeight+2*nameHeight);
269   return QRectF(p,s);
270 }
271
272
273 /* isInterface() : return true if there are some interfaces
274    with the given orientation (N,S,E,O)
275 */
276 bool AbstractBoxItem::isInterfaces(int orientation) const {
277   foreach(InterfaceItem* inter, interfaces) {
278     if (inter->getOrientation() == orientation) return true;
279   }
280   return false;
281 }
282
283 int AbstractBoxItem::nbInterfacesByOrientation(int orientation) {
284   int nb = 0;
285   foreach(InterfaceItem* inter, interfaces) {
286     if ((inter->visible) && (inter->getOrientation() == orientation)) nb++;
287   }
288   return nb;
289 }
290
291 void AbstractBoxItem::updateInterfacesAndConnections() {
292
293   // update all interfaces positions
294   foreach(InterfaceItem *item, interfaces){
295     item->updatePosition();
296   }
297   // NB: dunno the utility of this test !!
298   if (getScene() != NULL) {
299     // update all connections from/to this block
300     foreach(ConnectionItem *item, getScene()->getConnectionItems()){
301       if ((item->getFromInterfaceItem()->getOwner() == this) || (item->getToInterfaceItem()->getOwner() == this)) {
302         item->setPath();
303       }
304     }
305   }
306 }
307
308 void AbstractBoxItem::setDimension(int x, int y) {
309   boxWidth = x;
310   boxHeight = y;
311 }
312
313 InterfaceItem* AbstractBoxItem::getInterfaceFromCursor(qreal x, qreal y) {
314
315   foreach(InterfaceItem* inter, interfaces) {
316     if(x > inter->boundingRect().x() && x < (inter->boundingRect().x() + inter->boundingRect().width())){
317       if(y > inter->boundingRect().y() && y < (inter->boundingRect().y() + inter->boundingRect().height())){
318         return inter;
319       }
320     }
321   }
322   /* TO DO : check each interfaces if it contains x,y. If yes, return that interface */
323   return NULL;
324 }