229 lines
6.8 KiB
C++
229 lines
6.8 KiB
C++
#include "gui/network/NodeGraphic.h"
|
|
#include <QTextDocument>
|
|
#include <iostream>
|
|
#include <qgraphicsitem.h>
|
|
#include <qnamespace.h>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include "gui/network/DisplayFlagButton.h"
|
|
#include "gui/network/SocketGraphic.h"
|
|
#include <QGraphicsScene>
|
|
#include <QGraphicsSceneMouseEvent>
|
|
#include <QGraphicsSvgItem>
|
|
#include "gui/network/NodeIconGraphic.h"
|
|
|
|
NodeGraphic::NodeGraphic(QGraphicsItem *parent)
|
|
: QGraphicsItem(parent)
|
|
{
|
|
socketSize_ = 3;
|
|
titlePadding_=1;
|
|
titleText_ = "Attr_Del_1";
|
|
subTitleText_ = "Attribute Delete";
|
|
constexpr int height = 27;
|
|
constexpr int width = 100;
|
|
bodyRect_ = QRect(-width*0.5f, -height*0.5f, width, height);
|
|
iconScale_=height*0.55;
|
|
|
|
setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
|
|
|
|
initFonts();
|
|
initIcon();
|
|
initSockets();
|
|
initFlagButtons();
|
|
|
|
}
|
|
|
|
void NodeGraphic::initFonts()
|
|
{
|
|
// declare fonts
|
|
titleFont_ = QFont();
|
|
titleFont_.setPixelSize(8);
|
|
|
|
subTitleFont_ = QFont();
|
|
subTitleFont_.setPixelSize(5);
|
|
|
|
// compute text positions
|
|
QRectF titleBounds = QFontMetricsF(titleFont_).boundingRect(titleText_.c_str());
|
|
QRectF subTitleBounds = QFontMetricsF(subTitleFont_).boundingRect(subTitleText_.c_str());
|
|
float titleOffsetX = (titleBounds.width()-bodyRect_.width()-iconScale_)*0.5f;
|
|
float titleOffsetY = subTitleBounds.height()*0.5f+titlePadding_+(-(subTitleBounds.height()*0.5+titleBounds.height()+titlePadding_)+bodyRect_.height())*0.5f;
|
|
// float titleOffsetY = (bodyRect_.height())*0.5f;
|
|
// titleOffsetY -= subTitleBounds.height()*0.5f;
|
|
float subTitleOffsetX = titleOffsetX;
|
|
float subTitleOffsetY = (-(subTitleBounds.height()*0.5+titleBounds.height()+titlePadding_)+bodyRect_.height())*0.5f;
|
|
|
|
titleRect_ = bodyRect_.adjusted(-titleOffsetX, titleOffsetY, -titleOffsetX, titleOffsetY);
|
|
subTitleRect_ = bodyRect_.adjusted(-subTitleOffsetX, subTitleOffsetY, -subTitleOffsetX, subTitleOffsetY);
|
|
|
|
}
|
|
|
|
void NodeGraphic::initIcon()
|
|
{
|
|
icon_ = new NodeIconGraphic(":/node-icons/grid.svg", this);
|
|
// icon_ = new NodeIconGraphic("/home/parker/MyRepos/masters/static/icons/icon-main-white.svg", this);
|
|
|
|
icon_->setScale(1.0f/icon_->boundingRect().width()*iconScale_);
|
|
// icon_->setScale(0.01);
|
|
icon_->setPos(titleRect_.left()-iconScale_-iconPadding_, -iconScale_*0.5f);
|
|
}
|
|
|
|
void NodeGraphic::initFlagButtons()
|
|
{
|
|
displayFlagButton_ = new DisplayFlagButton(this);
|
|
float padding = 2;
|
|
displayFlagButton_->setPos(QPointF(bodyRect_.right()-displayFlagButton_->getWidth()/2.0f-padding, bodyRect_.center().y()));
|
|
}
|
|
|
|
void NodeGraphic::initSockets()
|
|
{
|
|
auto* socketInput = new SocketGraphic(SocketGraphic::SocketType::Input, this);
|
|
socketInput->setPos(getSocketPosition(0, SocketGraphic::SocketType::Input));
|
|
inputs_.push_back(socketInput);
|
|
|
|
auto* socketOutput = new SocketGraphic(SocketGraphic::SocketType::Output, this);
|
|
socketOutput->setPos(getSocketPosition(0, SocketGraphic::SocketType::Output));
|
|
outputs_.push_back(socketOutput);
|
|
}
|
|
|
|
// void setInputEdge(NodeEdgeGraphic* edge, int indx)
|
|
// {
|
|
|
|
// }
|
|
|
|
// void setOutputEdge(NodeEdgeGraphic* edge, int indx)
|
|
// {
|
|
|
|
// }
|
|
|
|
|
|
// void NodeGraphic::addEdge(NodeEdgeGraphic* edge)
|
|
// {
|
|
// edges_.push_back(edge);
|
|
// }
|
|
|
|
SocketGraphic* NodeGraphic::getInput(int indx) const
|
|
{
|
|
if(inputs_.size()==0)
|
|
{
|
|
throw std::out_of_range("Can't access inputs when node has no inputs: " + std::to_string(indx));
|
|
}
|
|
else if(indx>inputs_.size()-1)
|
|
{
|
|
throw std::out_of_range("Can't access input: " + std::to_string(indx));
|
|
}
|
|
return inputs_.at(indx);
|
|
}
|
|
SocketGraphic* NodeGraphic::getOutput(int indx) const
|
|
{
|
|
if(outputs_.size()==0)
|
|
{
|
|
throw std::out_of_range("Can't access outputs when node has no outputs: " + std::to_string(indx));
|
|
}
|
|
else if(indx>inputs_.size()-1)
|
|
{
|
|
throw std::out_of_range("Can't access input: " + std::to_string(indx));
|
|
}
|
|
return outputs_.at(indx);
|
|
}
|
|
|
|
QRectF NodeGraphic::boundingRect() const
|
|
{
|
|
QRectF boundRect = bodyRect_;
|
|
float padding = 0;
|
|
boundRect.adjust(-padding, -padding, padding, padding);
|
|
return boundRect;
|
|
}
|
|
|
|
void NodeGraphic::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
// default outline
|
|
QPen defaultPen = Qt::NoPen;
|
|
defaultPen.setWidth(1);
|
|
// outline when selected
|
|
QPen selectedPen = QPen("#edd044");
|
|
// choose outline
|
|
if(isSelected()) painter->setPen(selectedPen);
|
|
else painter->setPen(defaultPen);
|
|
|
|
// set fill
|
|
QBrush whiteBrush = QBrush("white");
|
|
painter->setBrush(QBrush(QColor("#1b1b1b")));
|
|
|
|
painter->drawRoundedRect(bodyRect_, 5, 5);
|
|
|
|
painter->setPen(QPen(QColor("white")));
|
|
|
|
painter->setFont(titleFont_);
|
|
// painter->setPen(QPen(QColor("#d2d2d2")));
|
|
painter->setPen(QPen(QColor("white")));
|
|
|
|
painter->drawText(titleRect_, Qt::AlignLeft, titleText_.c_str());
|
|
|
|
painter->setFont(subTitleFont_);
|
|
painter->drawText(subTitleRect_, Qt::AlignLeft, subTitleText_.c_str());
|
|
|
|
|
|
}
|
|
|
|
void NodeGraphic::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
QGraphicsItem::mouseMoveEvent(event);
|
|
updatePositions(event->scenePos());
|
|
}
|
|
|
|
// void NodeGraphic::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
|
// {
|
|
// updatePositions(event->scenePos());
|
|
// QGraphicsItem::mouseReleaseEvent(event);
|
|
// }
|
|
|
|
void NodeGraphic::updatePositions(QPointF pos)
|
|
{
|
|
// NOTE: in the future I might store socket ids as internal member variables,
|
|
// but for now I'm just going based on order
|
|
for(int socketIndex=0; socketIndex<inputs_.size(); ++socketIndex)
|
|
{
|
|
inputs_[socketIndex]->posChanged(getSocketScenePosition(socketIndex, SocketGraphic::SocketType::Input));
|
|
}
|
|
for(int socketIndex=0; socketIndex<outputs_.size(); ++socketIndex)
|
|
{
|
|
outputs_[socketIndex]->posChanged(getSocketScenePosition(socketIndex, SocketGraphic::SocketType::Output));
|
|
}
|
|
}
|
|
|
|
QPointF NodeGraphic::getSocketPosition(int socketIndex, SocketGraphic::SocketType socketType)
|
|
{
|
|
float xPos, yPos;
|
|
xPos = bodyRect_.center().x();
|
|
yPos = socketType == SocketGraphic::SocketType::Input ? bodyRect_.top() : bodyRect_.bottom();
|
|
|
|
return QPointF(xPos, yPos);
|
|
}
|
|
QPointF NodeGraphic::getSocketScenePosition(int socketIndex, SocketGraphic::SocketType socketType)
|
|
{
|
|
return this->pos()+getSocketPosition(socketIndex, socketType);
|
|
}
|
|
|
|
QRectF NodeGraphic::getBodyRect()
|
|
{
|
|
return bodyRect_;
|
|
}
|
|
|
|
|
|
|
|
// QVariant NodeGraphic::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
|
|
// {
|
|
// if (change == ItemPositionChange && scene()) {
|
|
// for(auto socket : inputs_)
|
|
// {
|
|
// socket->posChanged(value.toPointF());
|
|
// }
|
|
// for(auto socket : outputs_)
|
|
// {
|
|
// socket->posChanged(value.toPointF());
|
|
// }
|
|
// };
|
|
|
|
// return QGraphicsItem::itemChange(change, value);
|
|
// }
|