pgadmin3/hotdraw/figures/hdLineConnection.cpp
2020-07-07 22:19:12 +05:00

293 lines
6.4 KiB
C++

//////////////////////////////////////////////////////////////////////////
//
// pgAdmin III - PostgreSQL Tools
//
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
// hdLineConnection.cpp - Base class for line connection figure
//
//////////////////////////////////////////////////////////////////////////
#include "pgAdmin3.h"
// wxWindows headers
#include <wx/wx.h>
#include <wx/dcbuffer.h>
// App headers
#include "hotdraw/figures/hdLineConnection.h"
#include "hotdraw/handles/hdChangeConnectionStartHandle.h"
#include "hotdraw/handles/hdChangeConnectionEndHandle.h"
#include "hotdraw/handles/hdLineConnectionHandle.h"
#include "hotdraw/locators/hdPolyLineLocator.h"
#include "hotdraw/utilities/hdArrayCollection.h"
hdLineConnection::hdLineConnection():
hdPolyLineFigure()
{
startConnector = NULL;
endConnector = NULL;
changeConnStartHandle = NULL;
changeConnEndHandle = NULL;
}
hdLineConnection::hdLineConnection(int posIdx, hdIFigure *figure1, hdIFigure *figure2):
hdPolyLineFigure()
{
//Check figure available positions for diagrams, add at least needed to allow initialization of the class
int i, start;
start = basicDisplayBox.CountPositions();
for(i = start; i < (posIdx + 1); i++)
{
AddPosForNewDiagram();
}
startConnector = NULL;
endConnector = NULL;
if(figure1)
{
connectStart(figure1->connectorAt(posIdx, 0, 0));
}
if(figure2)
{
connectEnd(figure2->connectorAt(posIdx, 0, 0));
}
}
hdLineConnection::~hdLineConnection()
{
}
hdIConnector *hdLineConnection::getStartConnector()
{
return startConnector;
}
hdIConnector *hdLineConnection::getEndConnector()
{
return endConnector;
}
void hdLineConnection::setStartConnector(hdIConnector *connector)
{
startConnector = connector;
}
void hdLineConnection::setEndConnector(hdIConnector *connector)
{
endConnector = connector;
}
void hdLineConnection::connectStart(hdIConnector *start, hdDrawingView *view)
{
if(startConnector == start)
{
return;
}
disconnectStart();
startConnector = start;
connectFigure(startConnector);
}
void hdLineConnection::connectEnd(hdIConnector *end, hdDrawingView *view)
{
if(endConnector == end)
{
return;
}
disconnectEnd();
endConnector = end;
connectFigure(endConnector);
}
void hdLineConnection::disconnectStart(hdDrawingView *view)
{
disconnectFigure (startConnector);
startConnector = NULL;
}
void hdLineConnection::disconnectEnd(hdDrawingView *view)
{
disconnectFigure (endConnector);
endConnector = NULL;
}
bool hdLineConnection::canConnectStart(hdIFigure *figure)
{
return true;
}
bool hdLineConnection::canConnectEnd(hdIFigure *figure)
{
return true;
}
hdIFigure *hdLineConnection::getStartFigure()
{
if(startConnector)
{
return startConnector->getOwner();
}
return NULL;
}
hdIFigure *hdLineConnection::getEndFigure()
{
if(endConnector)
{
return endConnector->getOwner();
}
return NULL;
}
void hdLineConnection::updateConnection(int posIdx)
{
if(startConnector)
{
setStartPoint(posIdx, startConnector->findStart(posIdx, this));
}
if(endConnector)
{
setEndPoint(posIdx, endConnector->findEnd(posIdx, this));
}
}
hdIHandle *hdLineConnection::getStartHandle()
{
if(!changeConnStartHandle)
{
changeConnStartHandle = new hdChangeConnectionStartHandle(this);
}
return changeConnStartHandle;
}
hdIHandle *hdLineConnection::getEndHandle()
{
if(!changeConnEndHandle)
{
changeConnEndHandle = new hdChangeConnectionEndHandle(this);
}
return changeConnEndHandle;
}
void hdLineConnection::basicMoveBy(int posIdx, int x, int y)
{
hdPolyLineFigure::basicMoveBy(posIdx, x, y);
updateConnection(posIdx);
}
bool hdLineConnection::canConnect()
{
return false;
}
void hdLineConnection::setPointAt (int posIdx, int index, int x, int y)
{
hdPolyLineFigure::setPointAt(posIdx, index, x, y);
updateConnection(posIdx);
}
hdCollection *hdLineConnection::handlesEnumerator()
{
return handles;
}
void hdLineConnection::connectFigure (hdIConnector *connector)
{
if(connector)
{
connector->getOwner()->addObserver(this);
}
}
void hdLineConnection::disconnectFigure (hdIConnector *connector)
{
if(connector)
{
connector->getOwner()->removeObserver(this);
}
}
void hdLineConnection::onFigureChanged(int posIdx, hdIFigure *figure)
{
updateConnection(posIdx);
}
void hdLineConnection::addPoint (int posIdx, int x, int y)
{
willChange();
points[posIdx]->addItem((hdObject *) new hdPoint(x, y) );
//Update handles
if(points[posIdx]->count() == 1)
{
//first point add start handle
if(handles->count() == 0)
handles->addItem(getStartHandle());
}
else if(points[posIdx]->count() == 2)
{
//second point add end handle
if(handles->count() == 1)
handles->addItem(getEndHandle());
}
else if(points[posIdx]->count() > 2)
{
//Locate maximum index if there is need for one new handle then added it
if( getMaximunIndex() > handles->count() )
{
//third and above point, add a polylinehandle before end handle
handles->insertAtIndex(new hdPolyLineHandle(this, new hdPolyLineLocator(0), 0), handles->count() - 1);
}
}
updateHandlesIndexes();
changed(posIdx);
}
void hdLineConnection::insertPointAt (int posIdx, int index, int x, int y)
{
willChange();
points[posIdx]->insertAtIndex((hdObject *) new hdPoint(x, y), index);
//Update handles
//Is there need of a new handle if is first point
if(index == 0 && handles->count() == 0 )
{
//add a new handle "normal" for a point in next position 0,1 in 1... in 0 startHandle is not moved
handles->insertAtIndex(new hdPolyLineHandle(this, new hdPolyLineLocator(index), index), 1);
}
else if(index == (points[posIdx]->count() - 1) && handles->count() < getMaximunIndex() ) //last point
{
//add a new handle "normal" for a point in before last item position
handles->insertAtIndex(new hdPolyLineHandle(this, new hdPolyLineLocator(index), index), (points[posIdx]->count() - 1));
}
else if(handles->count() < getMaximunIndex())
{
//add handle at index
handles->insertAtIndex(new hdPolyLineHandle(this, new hdPolyLineLocator(index), index), index);
}
updateHandlesIndexes();
changed(posIdx);
}
//Update points between start and end, because start and end don't have index (is other kind of handle)
void hdLineConnection::updateHandlesIndexes()
{
hdPolyLineHandle *h = NULL;
//Get maximun point position in a collection of points
int maxPosition = getMaximunIndex();
//Update Handles indexes
for(int i = 1; i < maxPosition - 1; i++)
{
h = (hdPolyLineHandle *) handles->getItemAt(i);
h->setIndex(i);
}
}