OSDN Git Service

[denncoCreator] cell code scripts editor modification. Set editor readonly when a...
[dennco/denncoCreator.git] / Source / visualizer / dcglvisualizerwidget.cpp
1 //  Copyright (c) 2012 Dennco Project
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
16 //
17 //  Created by tkawata on Sep-30, 2012.
18 //
19 #include "TKLog.h"
20
21 #include "dcglvisualizerwidget.h"
22 #include "dcvcomponent.h"
23 #include "dcvpagecomponent.h"
24 #include "dcvcpage.h"
25
26 #include "dccreator.h"
27 #include "dcscene.h"
28 #include "dcanimationtimer.h"
29 #include "dccell.h"
30 #include "dcaxon.h"
31 #include "dcreceptor.h"
32 #include "utils/dccomponentutil.h"
33 #include "dcglwidget.h"
34
35 #include "dctoolwindowviewcontrol.h"
36 #include "dctoolwindowcelleditor.h"
37 #include "dctoolwindowterminalfromaxoneditor.h"
38 #include "dctoolwindowterminalfromreceptoreditor.h"
39
40 #include "eventhandler/dcveventhandler.h"
41 #include "utils/dcveventhandlerutil.h"
42 #include "codeeditor/dccellscriptseditorwindow.h"
43
44 #include <QtGui>
45 #include <QObject>
46 #include <QGLFormat>
47 #include <QtOpenGL>
48 #include <QDebug>
49 #if defined(Q_WS_WIN)
50     #include <GL/glu.h>
51 #else
52     #include <glu.h>
53 #endif
54 #include <typeinfo>
55
56 #ifndef GL_MULTISAMPLE
57 #define GL_MULTISAMPLE  0x809D
58 #endif
59
60 static QGraphicsView *s_uiView = NULL;
61
62
63 DCGLVisualizerWidget::DCGLVisualizerWidget(DCCreator *creator, QWidget *parent) : QGraphicsView(parent)
64 {
65     QGraphicsScene *scene = new DCUIGraphicsScene(creator, parent);
66     setScene(scene);
67
68     setViewport(DCGLWidget::singleton());
69     setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
70
71     setContextMenuPolicy(Qt::CustomContextMenu);
72     connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),scene, SLOT(showContextMenu(const QPoint&)));
73
74     s_uiView = this;
75 }
76
77 DCGLVisualizerWidget::~DCGLVisualizerWidget()
78 {
79 }
80
81 QPointF DCGLVisualizerWidget::globalPointToLocal(const QPoint &point)
82 {
83     if (s_uiView && s_uiView->scene())
84     {
85         return s_uiView->mapToScene(s_uiView->mapFromGlobal(point));
86     }
87     return QPoint();
88 }
89
90 bool toolWindowPositionLessThan(const DCGraphicsProxyWidget *t1, const DCGraphicsProxyWidget *t2)
91 {
92     if (t1->geometry().right() < t2->geometry().left())
93     {
94         return true;
95     }
96     else if (t2->geometry().right() < t1->geometry().left())
97     {
98         return false;
99     }
100
101     if (t1->pos().y() < t2->pos().y())
102     {
103         return true;
104     }
105     else if (t1->pos().y() == t2->pos().y())
106     {
107         if (t1->getPosPriority() < t2->getPosPriority())
108         {
109             return true;
110         }
111     }
112     return false;
113 }
114
115 void DCGLVisualizerWidget::resizeEvent(QResizeEvent *event) {
116     if (scene())
117     {
118         scene()->setSceneRect(QRect(QPoint(0, 0), event->size()));
119     }
120     QGraphicsView::resizeEvent(event);
121 }
122
123 void DCGLVisualizerWidget::setupViewport(QWidget *viewport)
124 {
125     QGLWidget *glWidget = dynamic_cast<QGLWidget*>(viewport);
126     glWidget->setAutoFillBackground(false);
127     glWidget->setMouseTracking(true);
128
129     if (glWidget)
130         glWidget->updateGL();
131 }
132
133 void DCGLVisualizerWidget::setVisible(bool visible)
134 {
135     QGraphicsView::setVisible(visible);
136 }
137
138 int DCGraphicsProxyWidget::getPosPriority() const
139 {
140     DCToolWindowBase *window = dynamic_cast<DCToolWindowBase*>(widget());
141     if (window)
142     {
143         return window->getPosPriority();
144     }
145     return 999;
146 }
147
148 DCGraphicsProxyWidget::DCGraphicsProxyWidget(DCSticky sticky, QGraphicsItem *parent, Qt::WindowFlags wFlags)
149     : QGraphicsProxyWidget(parent, wFlags), d_sticky(sticky), d_hasTargetPos(false), d_targetX(0), d_targetY(0),d_embeddedToolWindow(NULL)
150 {
151 }
152
153 DCGraphicsProxyWidget::~DCGraphicsProxyWidget()
154 {
155     this->disconnect();
156 }
157
158 void DCGraphicsProxyWidget::setTargetPos(float targetX, float targetY)
159 {
160     d_targetX = targetX;
161     d_targetY = targetY;
162     d_hasTargetPos = true;
163 }
164
165 void DCGraphicsProxyWidget::doAnimation()
166 {
167     const static int MINSPEED = 60;
168
169     if (!d_embeddedToolWindow)
170     {
171         d_embeddedToolWindow = dynamic_cast<DCToolWindowBase*>(widget());
172         if (!d_embeddedToolWindow)
173             return;
174     }
175
176     if (d_hasTargetPos)
177     {
178         QPointF p = pos();
179         float dx = d_targetX - p.x();
180         float dy = d_targetY - p.y();
181         float d = sqrt(dx * dx + dy * dy);
182         if (d < MINSPEED)
183         {
184             d_hasTargetPos = false;
185             setPos(d_targetX, d_targetY);
186         }
187         else
188         {
189             float speed = MINSPEED + d/3;
190             float sr = speed / d;
191             moveBy(dx * sr, dy * sr);
192         }
193     }
194
195     d_embeddedToolWindow->doAnimation();
196 }
197
198 QVariant DCGraphicsProxyWidget::itemChange(GraphicsItemChange change, const QVariant &value)
199 {
200     DCUIGraphicsScene *dcGraphicScene = dynamic_cast<DCUIGraphicsScene*>(scene());
201
202     if (change == ItemPositionChange && dcGraphicScene) {
203         QRectF rect = boundingRect();
204         QPointF pos = value.toPointF();
205
206         bool adjusted = false;
207
208         QRectF sceneRect = dcGraphicScene->sceneRect();
209
210         if (d_sticky == DC_STICKYWIDGET_LEFT && pos.x() + rect.left() > dcGraphicScene->getStickyAreaLeftWidth())
211         {
212             d_sticky = DC_STICKYWIDGET_NONE;
213         }
214         else if (d_sticky == DC_STICKYWIDGET_RIGHT && pos.x() + rect.width() < sceneRect.right() - dcGraphicScene->getStickyAreaRightWidth())
215         {
216             d_sticky = DC_STICKYWIDGET_NONE;
217         }
218
219         if (pos.x() + rect.left() < sceneRect.left() + 2)
220         {
221             d_sticky = DC_STICKYWIDGET_LEFT;
222             adjusted = true;
223             pos.setX(sceneRect.left() - rect.left() + 2);
224         }
225         else if (pos.x() + rect.right() >= sceneRect.right() - 2)
226         {
227             d_sticky = DC_STICKYWIDGET_RIGHT;
228             adjusted = true;
229             pos.setX(sceneRect.right() - rect.right() - 2);
230         }
231
232         if (pos.y() + rect.top() < sceneRect.top() + 2)
233         {
234             adjusted = true;
235             pos.setY(sceneRect.top() - rect.top() + 2);
236         }
237         else if (pos.y() + rect.bottom() >= sceneRect.bottom() - 2)
238         {
239             adjusted = true;
240             pos.setY(sceneRect.bottom() - rect.bottom() - 2);
241         }
242
243         if (adjusted)
244         {
245             widget()->move(pos.x(), pos.y());
246         }
247         return pos;
248     }
249     return QGraphicsProxyWidget::itemChange(change, value);
250 }
251
252 void DCGraphicsProxyWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
253 {
254     QGraphicsProxyWidget::resizeEvent(event);
255 }
256
257
258 DCUIGraphicsScene::DCUIGraphicsScene(DCCreator *creator, QWidget *parent)
259     : QGraphicsScene(parent), d_creator(creator), d_scene(NULL), d_eventHandler(NULL), d_isPaintForAnimation(false), d_requestRedraw(false),
260       d_inResigingDrag(false), d_dragStartX(0), d_dragStartY(0),
261       d_requestLayoutToolWindows(false), d_stickyAreaLeftWidth(10), d_stickyAreaRightWidth(10),
262       d_terminalFromAxonToolWindow(NULL),d_terminalFromReceptorToolWindow(NULL)
263 {
264     connect(d_creator, SIGNAL(sceneChanged(const void*, DCScene*)), this, SLOT(sceneChanged(const void*, DCScene*)));
265     connect(d_creator, SIGNAL(sceneSelectedPageChanged(const void*, const DCScene*)), this, SLOT(sceneSelectedPageChanged(const void*, const DCScene*)));
266     connect(d_creator, SIGNAL(sceneSelectedCellChanged(const void*, const DCScene*)), this, SLOT(sceneSelectedCellChanged(const void*, const DCScene*)));
267     connect(d_creator, SIGNAL(sceneViewAngleChanged(const void*,const DCScene*)), this, SLOT(sceneAngleChanged(const void*, const DCScene*)));
268     connect(d_creator, SIGNAL(sceneViewCenterChanged(const void*,const DCScene*)), this, SLOT(sceneCenterChanged(const void*, const DCScene*)));
269     connect(d_creator, SIGNAL(sceneViewScaleChanged(const void*, const DCScene*)), this, SLOT(sceneScaleChanged(const void*, const DCScene*)));
270     connect(d_creator, SIGNAL(sceneViewSettingChanged(const void*, const DCScene*)), this, SLOT(sceneSettingChanged(const void*, const DCScene*)));
271     connect(d_creator, SIGNAL(sceneViewEditModeChanged(const void*,const DCScene*)), this, SLOT(sceneEditModeChanged(const void*, const DCScene*)));
272     connect(d_creator, SIGNAL(destroyed(QObject*)), this, SLOT(creatorDestroyed()));
273     connect(d_creator, SIGNAL(commandExecuted(const QUndoCommand *)), this, SLOT(creatorCommandExecuted()));
274     connect(DCAnimationTimer::instance(), SIGNAL(goNextFrame()), this, SLOT(doAnimation()));
275     connect(this, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(resizeEvent(QRectF)));
276     d_viewControlTool = new DCToolWindowViewControl(d_creator);
277
278 }
279
280 DCUIGraphicsScene::~DCUIGraphicsScene()
281 {
282     if (d_creator)
283     {
284         d_creator->disconnect(this);
285     }
286     DCAnimationTimer::instance()->disconnect(this);
287
288     foreach (QGraphicsItem *item, items())
289     {
290         removeItem(item);
291     }
292
293     while (d_cellEditToolWindowPool.length() > 0)
294     {
295         DCToolWindowBase *window = d_cellEditToolWindowPool.takeFirst();
296         delete window;
297     }
298
299     while (d_cellEditToolWindowList.length() > 0)
300     {
301         DCToolWindowBase *window = d_cellEditToolWindowList.takeFirst();
302         removeToolWindow(window);
303         delete window;
304     }
305
306     if (d_terminalFromAxonToolWindow)
307     {
308         removeToolWindow(d_terminalFromAxonToolWindow);
309         delete d_terminalFromAxonToolWindow;
310     }
311 }
312
313
314 void DCUIGraphicsScene::addToolWindow(DCToolWindowBase *window, int x, int y, DCGraphicsProxyWidget::DCSticky sticky )
315 {
316     DCGraphicsProxyWidget *proxy = new DCGraphicsProxyWidget(sticky);
317     proxy->setWidget(window);
318     proxy->setZValue(1e30);
319     proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache);  // QGraphicsItem::ItemCoordinateCache
320     proxy->setFlag(QGraphicsItem::ItemIsMovable);
321     proxy->setFlag(QGraphicsItem::ItemIsSelectable, true);
322     proxy->setFlag(QGraphicsItem::ItemIsFocusable, true);
323
324     proxy->setPos(x,y);
325     addItem(proxy);
326     connect(window, SIGNAL(dragMoveFinished()), this, SLOT(requestLayoutToolWindows()));
327     connect(proxy, SIGNAL(heightChanged()), this, SLOT(requestLayoutToolWindows()));
328     connect(proxy, SIGNAL(widthChanged()), this, SLOT(requestLayoutToolWindows()));
329
330     requestLayoutToolWindows();
331 }
332
333 void DCUIGraphicsScene::removeToolWindow(DCToolWindowBase *window)
334 {
335     for (int i = items().length() - 1; i >= 0; i-- )
336     {
337         DCGraphicsProxyWidget *proxy = dynamic_cast<DCGraphicsProxyWidget*>(items().at(i));
338         if (proxy && proxy->widget() == window)
339         {
340             proxy->setWidget(NULL);
341             removeItem(proxy);
342             delete proxy;
343             break;
344         }
345     }
346     requestLayoutToolWindows();
347 }
348
349 void DCUIGraphicsScene::layoutToolWindows()
350 {
351     QList<DCGraphicsProxyWidget*> stickyListLeft;
352     QList<DCGraphicsProxyWidget*> stickyListRight;
353
354     foreach (QGraphicsItem *item, items())
355     {
356         DCGraphicsProxyWidget *proxy = dynamic_cast<DCGraphicsProxyWidget*>(item);
357         if (proxy)
358         {
359             switch(proxy->getSticky())
360             {
361             case DCGraphicsProxyWidget::DC_STICKYWIDGET_LEFT:
362                 stickyListLeft.append(proxy);
363                 break;
364             case DCGraphicsProxyWidget::DC_STICKYWIDGET_RIGHT:
365                 stickyListRight.append(proxy);
366                 break;
367             default:
368                 break;
369             }
370         }
371     }
372     qSort(stickyListLeft.begin(), stickyListLeft.end(), toolWindowPositionLessThan);
373     qSort(stickyListRight.begin(), stickyListRight.end(), toolWindowPositionLessThan);
374
375     QRectF srect = sceneRect();
376     QPointF pos(10, 10);
377     float xmax = 10;
378     for (int i = 0; i < stickyListLeft.length(); i++)
379     {
380         DCGraphicsProxyWidget *item = stickyListLeft.at(i);
381         const QRectF rect = item->boundingRect();
382         float tx = pos.x() - rect.x();
383         float ty =  pos.y() - rect.y();
384         if (ty + rect.height() > srect.height())
385         {
386             pos.setX(xmax + 10);
387             pos.setY(10);
388             tx = pos.x() - rect.x();
389             ty =  pos.y() - rect.y();
390         }
391         item->setTargetPos(tx, ty);
392         if (tx + rect.width() > xmax)
393             xmax = tx + rect.width();
394         pos += QPointF(0, 10 + rect.height());
395     }
396     d_stickyAreaLeftWidth = xmax;
397
398     pos.setX(srect.width() - 10);
399     pos.setY(srect.height() - 10);
400     float xmin = srect.width() - 10;
401     for (int i = stickyListRight.length() - 1; i >= 0 ; i--)
402     {
403         DCGraphicsProxyWidget *item = stickyListRight.at(i);
404         const QRectF rect = item->boundingRect();
405         float tx = pos.x() - rect.width() - rect.x();
406         float ty = pos.y() - rect.height() - rect.y();
407         if (ty < 0)
408         {
409             pos.setX(xmin - 10);
410             pos.setY(srect.height() - 10);
411             tx = pos.x() - rect.width() - rect.x();
412             ty = pos.y() - rect.height() - rect.y();
413         }
414         item->setTargetPos(tx, ty);
415         if (tx < xmin)
416             xmin = tx;
417         pos -= QPointF(0, 10 + rect.height());
418     }
419     d_stickyAreaRightWidth = srect.width() - xmin;
420
421     d_requestLayoutToolWindows = false;
422 }
423
424 void DCUIGraphicsScene::creatorDestroyed()
425 {
426     d_creator = NULL;
427 }
428
429 void DCUIGraphicsScene::sceneChanged(const void *requester, DCScene *scene)
430 {
431     DCScene::lockScene();
432     if (d_eventHandler)
433     {
434         delete d_eventHandler;
435         d_eventHandler = NULL;
436     }
437     if (d_scene)
438     {
439         d_scene->disconnect(d_viewControlTool);
440         d_scene->disconnect(this);
441     }
442     d_scene = scene;
443     if (d_scene)
444     {
445         d_viewControlTool->setDCScene(d_scene);
446         connect(d_scene, SIGNAL(viewPersModeChanged(const void*)), d_viewControlTool, SLOT(changeMode(const void*)));
447         connect(d_scene, SIGNAL(modeInitialized()), this, SLOT(initMode()));
448         connect(d_scene, SIGNAL(terminalEditCursorBelongingPageChagend(DCVCPage*)), this, SLOT(sceneTerminalEditPageBelongingChanged(DCVCPage*)));
449         connect(d_scene, SIGNAL(terminalEditCursorDropTargetChanged(DCVComponent*)), this, SLOT(sceneTerminalEditDropTargetChanged(DCVComponent*)));
450     }
451
452     while (!d_cellEditToolWindowList.isEmpty())
453     {
454         DCToolWindowBase *toolWindow = d_cellEditToolWindowList.takeFirst();
455         removeToolWindow(toolWindow);
456     }
457
458     DCScene::unlockScene();
459     updateView(false);
460 }
461
462 void DCUIGraphicsScene::sceneAngleChanged(const void* requester, const DCScene *scene)
463 {
464     if (d_scene != scene)
465         return;
466
467     d_requestRedraw = true;
468 }
469
470 void DCUIGraphicsScene::sceneCenterChanged(const void *requester, const DCScene *scene)
471 {
472     if (d_scene != scene)
473         return;
474
475     d_requestRedraw = true;
476 }
477
478 void DCUIGraphicsScene::sceneScaleChanged(const void* requester, const DCScene *scene)
479 {
480     if (d_scene != scene)
481         return;
482
483     d_requestRedraw = true;
484 }
485
486 void DCUIGraphicsScene::sceneSettingChanged(const void* requester, const DCScene *scene)
487 {
488     if (d_scene != scene)
489         return;
490
491     d_requestRedraw = true;
492 }
493
494 void DCUIGraphicsScene::sceneSelectedPageChanged(const void* requester, const DCScene *scene)
495 {
496     if (d_scene != scene)
497         return;
498
499     if (d_eventHandler)
500         d_eventHandler->selectedPageChanged(requester);
501
502     d_requestRedraw = true;
503 }
504
505
506 void DCUIGraphicsScene::sceneSelectedCellChanged(const void* requester, const DCScene *scene)
507 {
508     if (d_scene != scene)
509         return;
510
511     switch (scene->getEditMode())
512     {
513     case DCScene::DCV_EDITMODE_LAYOUT:
514         updateCellEditorToolWindows();
515         break;
516
517     case DCScene::DCV_EDITMODE_TERMINAL_FROM_AXON:
518         break;
519
520     case DCScene::DCV_EDITMODE_TERMINAL_FROM_RECEPTOR:
521         break;
522
523     }
524
525     d_requestRedraw = true;
526 }
527
528 void DCUIGraphicsScene::sceneEditModeChanged(const void *requester, const DCScene *scene)
529 {
530
531     if (d_scene != scene)
532         return;
533
534     if (d_eventHandler && scene->getEditMode() == d_eventHandler->getHandlerType() &&  d_scene == d_eventHandler->getScene())
535         return;
536
537     if (d_eventHandler)
538     {
539         delete d_eventHandler;
540         d_eventHandler = NULL;
541     }
542
543     switch (scene->getEditMode())
544     {
545     case DCScene::DCV_EDITMODE_LAYOUT:
546         closeTerminalFromAxonToolWindow();
547         closeTerminalFromReceptorToolWindow();
548         showCellEditorToolWindows();
549         d_eventHandler = DCVEventHandlerUtil::createLayoutModeHandler(this, d_creator, d_scene);
550         break;
551
552     case DCScene::DCV_EDITMODE_TERMINAL_FROM_AXON:
553         closeAllCellEditorToolWindows();
554         closeTerminalFromReceptorToolWindow();
555         showTerminalFromAxonToolWindow();
556         d_eventHandler = DCVEventHandlerUtil::createTerminalFromAxonModeHandler(this, d_creator, d_scene, scene->getEditAxon(), scene->getTerminalEditCursor());
557         break;
558
559     case DCScene::DCV_EDITMODE_TERMINAL_FROM_RECEPTOR:
560         closeAllCellEditorToolWindows();
561         closeTerminalFromAxonToolWindow();
562         showTerminalFromReceptorToolWindow();
563         d_eventHandler = DCVEventHandlerUtil::createTerminalFromReceptorModeHandler(this, d_creator, d_scene, scene->getEditReceptor(), scene->getTerminalEditCursor());
564         break;
565
566     }
567     requestRedraw(false);
568 }
569
570 void DCUIGraphicsScene::sceneTerminalEditPageBelongingChanged(DCVCPage *page)
571 {
572     switch (d_scene->getEditMode())
573     {
574     case DCScene::DCV_EDITMODE_LAYOUT:
575         break;
576
577     case DCScene::DCV_EDITMODE_TERMINAL_FROM_AXON:
578         updateTerminalFromAxonToolWindow();
579         break;
580
581     case DCScene::DCV_EDITMODE_TERMINAL_FROM_RECEPTOR:
582         updateTerminalFromReceptorToolWindow();
583         break;
584
585     }
586
587     d_requestRedraw = true;
588 }
589
590 void DCUIGraphicsScene::sceneTerminalEditDropTargetChanged(DCVComponent *dropTarget)
591 {
592     switch (d_scene->getEditMode())
593     {
594     case DCScene::DCV_EDITMODE_LAYOUT:
595         break;
596
597     case DCScene::DCV_EDITMODE_TERMINAL_FROM_AXON:
598         updateTerminalFromAxonToolWindow();
599         break;
600
601     case DCScene::DCV_EDITMODE_TERMINAL_FROM_RECEPTOR:
602         updateTerminalFromReceptorToolWindow();
603         break;
604
605     }
606
607     d_requestRedraw = true;
608 }
609
610 void DCUIGraphicsScene::setupProjection()
611 {
612     if (!d_creator || !d_scene)
613         return;
614
615     float _width = width();
616     float _height = height();
617     float _scale = d_scene->getScale();
618     glViewport(0, 0, _width, _height);
619     glMatrixMode(GL_PROJECTION);
620     glLoadIdentity();
621     glOrtho(-_width / _scale, _width / _scale, -_height / _scale, _height / _scale, -100.0, 100.0);
622
623     setupCamera();
624
625     glGetDoublev(GL_PROJECTION_MATRIX, d_projectionMatrix);
626     glGetIntegerv(GL_VIEWPORT, d_viewportMatrix);
627
628 }
629
630 void DCUIGraphicsScene::setupCamera()
631 {
632     glTranslatef(- d_scene->getCenterX(),  d_scene->getCenterEditModeY(), 0);
633     glRotatef(d_scene->getXAngle(),1,0,0);
634     glRotatef(d_scene->getYAngle(),0,1,0);
635     glTranslatef(0, - d_scene->getCenterBrowsModeY(), 0);
636 }
637
638 void DCUIGraphicsScene::updateView(bool isAnimationInterval)
639 {
640     DCScene::lockScene();
641
642     DCGLWidget::singleton()->makeCurrent();
643
644     d_isPaintForAnimation = isAnimationInterval;
645     d_requestRedraw = false;
646
647     update();
648 }
649
650 void DCUIGraphicsScene::requestRedraw(bool immediate)
651 {
652     if (immediate)
653         updateView(false);
654     else
655         d_requestRedraw = true;
656 }
657
658 DCVComponent* DCUIGraphicsScene::getObjectAt(int viewX, int viewY, DCVComponent *priorityObject)
659 {
660     if (!d_creator || !d_scene)
661         return NULL;
662
663     DCScene::lockScene();
664
665     DCGLWidget::singleton()->makeCurrent();
666
667     float _width = width();
668     float _height = height();
669     float _scale = d_scene->getScale();
670
671     GLuint selectionBuffer[512];
672     glSelectBuffer(512, selectionBuffer);
673     glRenderMode(GL_SELECT);
674     glInitNames();
675     glPushName(0);
676
677     glMatrixMode(GL_PROJECTION);
678     glPushMatrix();
679     glLoadIdentity();
680     int viewportMat[4];
681     memcpy(viewportMat, d_viewportMatrix, sizeof(viewportMat));
682     gluPickMatrix(viewX,viewportMat[3] - viewY, 4,4,viewportMat);
683     glOrtho(-_width / _scale, _width / _scale, -_height / _scale, _height / _scale, -100.0, 100.0);
684
685     setupCamera();
686
687     QList<DCVComponent *> itemList;
688     glMatrixMode(GL_MODELVIEW);
689     glPushMatrix();
690     d_scene->drawForSelection(&itemList);
691     glPopMatrix();
692
693     glMatrixMode(GL_PROJECTION);
694     glPopMatrix();
695
696     glFlush();
697     glMatrixMode(GL_MODELVIEW);
698
699     int items = glRenderMode(GL_RENDER);
700     DCVComponent *selectedObject = NULL;
701     DCVComponent *selectedPage = NULL;
702     int idx = 0;
703     unsigned int minDepthPage = UINT_MAX;
704     unsigned int minDepthObject = UINT_MAX;
705     if (priorityObject)
706     {
707         for (int i = 0; i < items; i++)
708         {
709             unsigned int nameLen = selectionBuffer[idx];
710             unsigned int min = selectionBuffer[idx + 1];
711             unsigned int nameId = selectionBuffer[idx + 3];
712
713             if (nameLen == 1 && nameId < (unsigned int) itemList.length())
714             {
715                 DCVComponent *obj = itemList[nameId];
716                 if (priorityObject == obj)
717                 {
718                     selectedObject = obj;
719                     break;
720                 }
721                 if (obj->getPageBelonging() == obj)
722                 {
723                     if (min < minDepthPage)
724                     {
725                         minDepthPage = min;
726                         selectedPage = obj;
727                     }
728                 }
729                 else
730                 {
731                     if (obj->getIsSelectable() &&  min < minDepthObject)
732                     {
733                         minDepthObject = min;
734                         selectedObject = obj;
735                     }
736                 }
737             }
738             idx += nameLen + 3;
739         }
740     }
741     else
742     {
743         for (int i = 0; i < items; i++)
744         {
745             unsigned int nameLen = selectionBuffer[idx];
746             unsigned int min = selectionBuffer[idx + 1];
747             unsigned int nameId = selectionBuffer[idx + 3];
748
749             if (nameLen == 1 && nameId < (unsigned int) itemList.length())
750             {
751                 DCVComponent *obj = itemList[nameId];
752                 if (obj->getPageBelonging() == obj)
753                 {
754                     if (min < minDepthPage)
755                     {
756                         minDepthPage = min;
757                         selectedPage = obj;
758                     }
759                 }
760                 else
761                 {
762                     if (obj->getIsSelectable() &&  min < minDepthObject)
763                     {
764                         minDepthObject = min;
765                         selectedObject = obj;
766                     }
767                 }
768             }
769             idx += nameLen + 3;
770         }
771     }
772
773     DCScene::unlockScene();
774
775     return selectedObject ? selectedObject : selectedPage;
776 }
777
778 //slot
779 void DCUIGraphicsScene::initMode()
780 {
781     sceneEditModeChanged(NULL, d_scene);
782 }
783
784 //slot
785 void DCUIGraphicsScene::doAnimation()
786 {
787     if (d_requestLayoutToolWindows)
788     {
789         layoutToolWindows();
790     }
791
792     foreach (QGraphicsItem *item, items())
793     {
794         DCGraphicsProxyWidget *proxy = dynamic_cast<DCGraphicsProxyWidget*>(item);
795         if (proxy)
796         {
797             proxy->doAnimation();
798         }
799     }
800
801     if (!d_creator || !d_scene)
802         return;
803
804     if (DCScene::getShouldContinueAnimation())
805     {
806         bool r = d_scene->doAnimation();
807         DCScene::setShouldContinueAnimation(r);
808         updateView(true);
809     }
810     else if (d_requestRedraw)
811     {
812         updateView(false);
813     }
814 }
815
816
817 void DCUIGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
818 {
819     painter->beginNativePainting();
820     setStates();
821
822     paintGL();
823
824     defaultStates();
825     painter->endNativePainting();
826 }
827
828 void DCUIGraphicsScene::setStates()
829 {
830     glPushAttrib(GL_ALL_ATTRIB_BITS);
831
832     glMatrixMode(GL_PROJECTION);
833     glPushMatrix();
834     glLoadIdentity();
835
836     glMatrixMode(GL_MODELVIEW);
837     glPushMatrix();
838     glLoadIdentity();
839
840     initializeGL();
841     glBindTexture(GL_TEXTURE_2D, 0);
842
843 }
844
845 void DCUIGraphicsScene::defaultStates()
846 {
847     glPopAttrib();
848
849     glMatrixMode(GL_MODELVIEW);
850     glPopMatrix();
851
852     glMatrixMode(GL_PROJECTION);
853     glPopMatrix();
854
855 }
856
857 void DCUIGraphicsScene::initializeGL()
858 {
859     glClearColor(0.0, 0.0, 0.0, 1.0);
860     glEnable(GL_TEXTURE_2D);
861     glEnable(GL_MULTISAMPLE);
862     glEnable(GL_CULL_FACE);
863     glEnable(GL_DEPTH_TEST);
864     glDisable(GL_LIGHTING);
865     glDisable(GL_COLOR_MATERIAL);
866     glDisable(GL_LIGHT0);
867     glDisable(GL_NORMALIZE);
868 }
869
870 void DCUIGraphicsScene::paintGL()
871 {
872     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
873
874     setupProjection();
875
876     DCScene::lockScene();
877     glMatrixMode(GL_MODELVIEW);
878     if (d_scene)
879     {
880         glPushMatrix();
881         d_scene->draw(d_isPaintForAnimation);
882         glPopMatrix();
883     }
884     d_isPaintForAnimation = false;
885     glFlush();
886     DCScene::unlockScene();
887 }
888
889 void DCUIGraphicsScene::resizeEvent(const QRectF & rect)
890 {
891     updateView(false);
892     requestLayoutToolWindows();
893 }
894
895 void DCUIGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *event)
896 {
897     QGraphicsScene::mousePressEvent(event);
898     if (event->isAccepted()) return;
899
900     if (!d_creator || !d_scene || d_scene->getIsInModeTransition())
901         return;
902
903     QPointF mousePos = event->scenePos();
904     d_dragStartX = mousePos.x();
905     d_dragStartY = mousePos.y();
906
907     d_clickTime.start();
908
909     if (d_eventHandler)
910         d_eventHandler->mousePressEvent(event);
911 }
912
913 void DCUIGraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
914 {
915     QGraphicsScene::mousePressEvent(event);
916     if (event->isAccepted()) return;
917
918     if (!d_creator || !d_scene || d_scene->getIsInModeTransition())
919         return;
920
921     if (d_eventHandler)
922         d_eventHandler->mouseDoubleClickEvent(event);
923 }
924
925 void DCUIGraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
926 {
927     QGraphicsScene::mouseMoveEvent(event);
928     if (event->isAccepted()) return;
929
930     if (!d_creator || !d_scene || d_scene->getIsInModeTransition())
931         return;
932
933     if (d_eventHandler)
934         d_eventHandler->mouseMoveEvent(event, d_clickTime.elapsed());
935 }
936
937 void DCUIGraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
938 {
939     QGraphicsScene::mouseReleaseEvent(event);
940     if (event->isAccepted()) return;
941     if (!d_creator || !d_scene || d_scene->getIsInModeTransition())
942         return;
943
944     QPointF mousePos = event->scenePos();
945
946     int dx = mousePos.x() - d_dragStartX;
947     int dy = mousePos.y() - d_dragStartY;
948
949     bool wasDrag = !(d_clickTime.elapsed() < 500 && dx * dx + dy * dy < 400);
950
951     DCGLWidget::singleton()->setCursor(Qt::ArrowCursor);
952
953     if (d_eventHandler)
954         d_eventHandler->mouseReleaseEvent(event, wasDrag);
955 }
956
957 void DCUIGraphicsScene::wheelEvent(QGraphicsSceneWheelEvent  *event)
958 {
959     QGraphicsScene::wheelEvent(event);
960
961     if (!d_creator || !d_scene)
962         return;
963
964     if (d_eventHandler)
965         d_eventHandler->wheelEvent(event);
966 }
967
968 void DCUIGraphicsScene::keyPressEvent(QKeyEvent *event)
969 {
970     QGraphicsScene::keyPressEvent(event);
971     if (event->isAccepted()) return;
972
973     if (!d_creator || !d_scene)
974         return;
975
976     if (d_eventHandler)
977         d_eventHandler->keyPressEvent(event);
978 }
979
980 void DCUIGraphicsScene::keyReleaseEvent(QKeyEvent *event)
981 {
982     QGraphicsScene::keyReleaseEvent(event);
983     if (event->isAccepted()) return;
984
985     if (d_eventHandler)
986         d_eventHandler->keyReleaseEvent(event);
987 }
988
989 void DCUIGraphicsScene::showContextMenu(const QPoint &pos)
990 {
991     if (!d_creator || !d_scene)
992         return;
993
994     if (d_eventHandler)
995     {
996         d_eventHandler->showContextMenu(pos);
997     }
998 }
999
1000 void DCUIGraphicsScene::menuActionEditThisPage()
1001 {
1002     if (!d_creator || !d_scene)
1003         return;
1004
1005     d_creator->changePersMode(this, DCCreator::DC_PERSMODE_NAVIGATION);
1006 }
1007
1008 void DCUIGraphicsScene::menuActionEditCellCode()
1009 {
1010     if (!d_creator || !d_scene)
1011         return;
1012
1013     DCCell *cell = NULL;
1014     bool isSingleCellSelection = false;
1015     QList<DCVComponent*>  list = d_scene->getSelectedCellObjects();
1016     for (int i = 0; i < list.size(); i++)
1017     {
1018         if (cell && cell != list.at(i)->getOwnerCell())
1019         {
1020             isSingleCellSelection = false;
1021             break;
1022         }
1023         else if (cell == NULL)
1024         {
1025             cell = list.at(i)->getOwnerCell();
1026         }
1027     }
1028     DCCellScriptsEditorWindow::startEditing(cell);
1029 }
1030
1031 void DCUIGraphicsScene::menuActionFinishEditMode()
1032 {
1033     if (!d_creator || !d_scene)
1034         return;
1035
1036     d_creator->changePersMode(this, DCCreator::DC_PERSMODE_PAGEEDIT);
1037 }
1038
1039 void DCUIGraphicsScene::menuActionEditReceptor()
1040 {
1041     if (!d_creator || !d_scene)
1042         return;
1043
1044     //TODO
1045 }
1046
1047 void DCUIGraphicsScene::menuActionEditAxonTerminal()
1048 {
1049     if (!d_creator || !d_scene)
1050         return;
1051
1052     //TODO
1053 }
1054
1055 void DCUIGraphicsScene::menuActionSaveChangeAll()
1056 {
1057     if (!d_creator || !d_scene)
1058         return;
1059
1060     d_creator->saveAll(true);
1061 }
1062
1063 void DCUIGraphicsScene::creatorCommandExecuted()
1064 {
1065     switch (d_scene->getEditMode())
1066     {
1067     case DCScene::DCV_EDITMODE_LAYOUT:
1068         updateCellEditorToolWindows();
1069         break;
1070
1071     case DCScene::DCV_EDITMODE_TERMINAL_FROM_AXON:
1072         break;
1073
1074     case DCScene::DCV_EDITMODE_TERMINAL_FROM_RECEPTOR:
1075         break;
1076
1077     }
1078
1079     d_requestRedraw = true;
1080 }
1081
1082 bool DCUIGraphicsScene::toObjectCoordinateXZ(float viewX, float viewY, DCVComponent *object, float *pLocalX, float *pLocalZ)
1083 {
1084     double localX0, localY0, localZ0;
1085     double localX1, localY1, localZ1;
1086
1087     gluUnProject(viewX,  d_viewportMatrix[3] - viewY, 0, object->getModelViewMatrix(), d_projectionMatrix, d_viewportMatrix, &localX0, &localY0, &localZ0);
1088     gluUnProject(viewX,  d_viewportMatrix[3] - viewY, 1, object->getModelViewMatrix(), d_projectionMatrix, d_viewportMatrix, &localX1, &localY1, &localZ1);
1089     double dx = localX1 - localX0;
1090     double dy = localY1 - localY0;
1091     double dz = localZ1 - localZ0;
1092     if (dy == 0)
1093     {
1094         *pLocalX = 0;
1095         *pLocalZ = 0;
1096         return false;
1097     }
1098     else
1099     {
1100         *pLocalX = -(dx * localY0 - dy * localX0)/dy;
1101         *pLocalZ = -(dz * localY0 - dy * localZ0)/dy;
1102     }
1103     return true;
1104 }
1105
1106 void DCUIGraphicsScene::showCellEditorToolWindows()
1107 {
1108     updateCellEditorToolWindows();
1109 }
1110
1111 void DCUIGraphicsScene::updateCellEditorToolWindows()
1112 {
1113     QList<DCVComponent*> selectedList = d_scene->getSelectedCellObjects();
1114
1115     for (int i = d_cellEditToolWindowList.length() - 1; i >= 0 ; i--)
1116     {
1117         DCToolWindowCellEditor *window = d_cellEditToolWindowList.at(i);
1118         if (window->getCell() == NULL || !window->getCell()->getVComponent()->getIsSelected())
1119         {
1120             removeToolWindow(window);
1121             d_cellEditToolWindowList.takeAt(i);
1122             d_cellEditToolWindowPool.push_back(window);
1123         }
1124         else
1125         {
1126             window->updateView();
1127             requestLayoutToolWindows();
1128         }
1129     }
1130
1131     for (int i = 0; i < selectedList.length(); i++)
1132     {
1133         bool found = false;
1134         for (int j = 0 ; j < d_cellEditToolWindowList.length(); j++)
1135         {
1136             if (d_cellEditToolWindowList.at(j)->getCell() == selectedList.at(i)->getOwnerCell())
1137             {
1138                 found = true;
1139                 break;
1140             }
1141         }
1142         if (!found)
1143         {
1144             DCToolWindowCellEditor *window = NULL;
1145             if (d_cellEditToolWindowPool.length() > 0)
1146             {
1147                 window = d_cellEditToolWindowPool.takeFirst();
1148             }
1149             else
1150             {
1151                 window = new DCToolWindowCellEditor(d_creator);
1152             }
1153             addToolWindow(window);
1154             window->setCell(selectedList.at(i)->getOwnerCell());
1155             d_cellEditToolWindowList.append(window);
1156         }
1157     }
1158 }
1159
1160 void DCUIGraphicsScene::closeAllCellEditorToolWindows()
1161 {
1162     while (d_cellEditToolWindowList.length() > 0)
1163     {
1164         DCToolWindowCellEditor *window = d_cellEditToolWindowList.takeFirst();
1165         removeToolWindow(window);
1166         d_cellEditToolWindowPool.push_back(window);
1167     }
1168     requestLayoutToolWindows();
1169 }
1170
1171 void DCUIGraphicsScene::showTerminalFromAxonToolWindow()
1172 {
1173     if (d_terminalFromAxonToolWindow == NULL)
1174     {
1175         d_terminalFromAxonToolWindow = new DCToolWindowTerminalFromAxon(d_creator);
1176     }
1177     updateTerminalFromAxonToolWindow();
1178     addToolWindow(d_terminalFromAxonToolWindow);
1179 }
1180
1181 void DCUIGraphicsScene::updateTerminalFromAxonToolWindow()
1182 {
1183     if (d_terminalFromAxonToolWindow)
1184     {
1185         d_terminalFromAxonToolWindow->updateData(d_scene->getEditAxon()->getOwnerCell(),
1186                                                  d_scene->getTerminalEditCursorLocationString(),
1187                                                  d_scene->getTerminalEditCursorDropTarget() ? d_scene->getTerminalEditCursorDropTarget()->getOwnerCell() : NULL);
1188     }
1189 }
1190
1191 void DCUIGraphicsScene::closeTerminalFromAxonToolWindow()
1192 {
1193     if (d_terminalFromAxonToolWindow)
1194     {
1195         removeToolWindow(d_terminalFromAxonToolWindow);
1196     }
1197 }
1198
1199 void DCUIGraphicsScene::showTerminalFromReceptorToolWindow()
1200 {
1201     if (d_terminalFromReceptorToolWindow == NULL)
1202     {
1203         d_terminalFromReceptorToolWindow = new DCToolWindowTerminalFromReceptor(d_creator);
1204     }
1205     updateTerminalFromReceptorToolWindow();
1206     addToolWindow(d_terminalFromReceptorToolWindow);
1207 }
1208
1209 void DCUIGraphicsScene::updateTerminalFromReceptorToolWindow()
1210 {
1211     if (d_terminalFromReceptorToolWindow)
1212     {
1213         DCReceptor *receptor = d_scene->getEditReceptor();
1214          if (receptor)
1215            d_terminalFromReceptorToolWindow->updateData(receptor->getOwnerCell(),
1216                                                          receptor,
1217                                                          d_scene->getTerminalEditCursorLocationString(),
1218                                                          d_scene->getTerminalEditCursorDropTarget() ? d_scene->getTerminalEditCursorDropTarget()->getOwnerCell() : NULL);
1219     }
1220 }
1221
1222 void DCUIGraphicsScene::closeTerminalFromReceptorToolWindow()
1223 {
1224     if (d_terminalFromReceptorToolWindow)
1225     {
1226         d_terminalFromReceptorToolWindow->resetData();
1227         removeToolWindow(d_terminalFromReceptorToolWindow);
1228     }
1229 }