You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
440 lines
10 KiB
440 lines
10 KiB
15 years ago
|
/*
|
||
|
|
||
|
Copyright (C) 1998-1999 Stefan Westerfeld
|
||
|
stefan@space.twc.de
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||
|
|
||
|
*/
|
||
|
|
||
|
#include "module.h"
|
||
|
#include "drawutils.h"
|
||
|
#include <stdio.h>
|
||
|
#include <arts/debug.h>
|
||
|
|
||
|
#include <qpalette.h>
|
||
|
#include <qdrawutil.h>
|
||
|
#include <kiconloader.h>
|
||
|
#include <algorithm>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
ModulePort::ModulePort(StructureComponent *owner, const string& description,
|
||
|
int drawsegment, Direction direction, Arts::PortDesc PortDesc)
|
||
|
{
|
||
|
selected = false;
|
||
|
|
||
|
this->owner = owner; // whats the syntax for that again?
|
||
|
this->drawsegment = drawsegment;
|
||
|
this->direction = direction;
|
||
|
this->PortDesc = PortDesc;
|
||
|
this->description = description.c_str();
|
||
|
|
||
|
pdID = PortDesc.ID();
|
||
|
|
||
|
isinitarg = (PortDesc.type().connType == Arts::conn_property);
|
||
|
if(isinitarg) arts_debug("port %s is an init arg", (const char *)this->description.latin1());
|
||
|
arts_debug("port %s created", (const char *)this->description.latin1());
|
||
|
conntype = none;
|
||
|
route_owner = 0;
|
||
|
}
|
||
|
|
||
|
bool ModulePort::down()
|
||
|
{
|
||
|
return (PortDesc.isConnected() || PortDesc.hasValue() || selected);
|
||
|
}
|
||
|
|
||
|
QColor ModulePort::color(bool isInterface)
|
||
|
{
|
||
|
if(selected) return QColor(255, 165, 0);
|
||
|
|
||
|
if(PortDesc.hasValue())
|
||
|
{
|
||
|
if(isinitarg) return QColor(180, 180, 180);
|
||
|
return QColor(100, 100, 255);
|
||
|
}
|
||
|
|
||
|
if(isinitarg) return QColor(128, 128, 128);
|
||
|
|
||
|
if(isInterface) return QColor(100, 100, 100);
|
||
|
return QColor(43, 43, 168);
|
||
|
}
|
||
|
|
||
|
Module::Module(Arts::ModuleDesc module, Arts::StructureDesc structuredesc,
|
||
|
StructureCanvas *canvas) : StructureComponent(canvas)
|
||
|
{
|
||
|
StructureDesc = structuredesc;
|
||
|
ModuleDesc = module;
|
||
|
|
||
|
_x = ModuleDesc.x();
|
||
|
_y = ModuleDesc.y();
|
||
|
initModule();
|
||
|
}
|
||
|
|
||
|
Module::Module(const Arts::ModuleInfo& minfo, Arts::StructureDesc structuredesc,
|
||
|
StructureCanvas *canvas) : StructureComponent(canvas)
|
||
|
{
|
||
|
StructureDesc = structuredesc;
|
||
|
ModuleDesc = StructureDesc.createModuleDesc(minfo);
|
||
|
|
||
|
initModule();
|
||
|
}
|
||
|
|
||
|
void Module::initModule()
|
||
|
{
|
||
|
QString iconname;
|
||
|
KIconLoader iconloader;
|
||
|
|
||
|
_selected = false;
|
||
|
_visible = false;
|
||
|
_height = 1;
|
||
|
_name = ModuleDesc.name().c_str();
|
||
|
_pixmap = NULL;
|
||
|
|
||
|
// test if pixmap available
|
||
|
|
||
|
iconname = _name + ".xpm";
|
||
|
|
||
|
_pixmap = new QPixmap(iconloader.loadIcon(iconname, KIcon::User));
|
||
|
if(!_pixmap->height())
|
||
|
{
|
||
|
iconname = _name + ".png";
|
||
|
delete _pixmap;
|
||
|
_pixmap = new QPixmap( iconloader.loadIcon( iconname, KIcon::User ) );
|
||
|
if( !_pixmap->height() )
|
||
|
{
|
||
|
delete _pixmap;
|
||
|
_pixmap = 0;
|
||
|
}
|
||
|
}
|
||
|
// try again without Arts:: - prefix
|
||
|
|
||
|
if(iconname.startsWith("Arts::"))
|
||
|
{
|
||
|
iconname = iconname.mid(6);
|
||
|
|
||
|
_pixmap = new QPixmap(iconloader.loadIcon(iconname, KIcon::User));
|
||
|
if(!_pixmap->height())
|
||
|
{
|
||
|
iconname.replace( iconname.length() - 4, 3, "png" );
|
||
|
delete _pixmap;
|
||
|
_pixmap = new QPixmap(iconloader.loadIcon(iconname, KIcon::User));
|
||
|
if( !_pixmap->height() )
|
||
|
{
|
||
|
delete _pixmap;
|
||
|
_pixmap = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/*
|
||
|
FILE *test = fopen(QFile::encodeName(iconname), "r");
|
||
|
if(test)
|
||
|
{
|
||
|
pixmap = new QPixmap(iconname);
|
||
|
fclose(test);
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
// create lists with inports & outports for this module
|
||
|
// and bind them to it ...
|
||
|
|
||
|
arts_debug("Getting ports...");
|
||
|
vector<Arts::PortDesc >*ports = ModuleDesc.ports();
|
||
|
unsigned long portpos;
|
||
|
long indraw = 1, outdraw = 2;
|
||
|
|
||
|
for(portpos = 0; portpos < ports->size(); portpos++)
|
||
|
{
|
||
|
Arts::PortDesc pd = (*ports)[portpos];
|
||
|
ModulePort *p;
|
||
|
|
||
|
arts_debug("CREATING %s", pd.name().c_str());
|
||
|
switch(pd.type().direction)
|
||
|
{
|
||
|
case Arts::input:
|
||
|
p = new ModulePort(this, pd.name(), indraw++,
|
||
|
ModulePort::in, pd);
|
||
|
inports.push_back(p);
|
||
|
break;
|
||
|
case Arts::output:
|
||
|
p = new ModulePort(this, pd.name(), outdraw++,
|
||
|
ModulePort::out, pd);
|
||
|
outports.push_back(p);
|
||
|
break;
|
||
|
default:
|
||
|
assert(false); // shouldn't happen!
|
||
|
}
|
||
|
}
|
||
|
|
||
|
delete ports;
|
||
|
|
||
|
_width = 1 + max(inports.size(), outports.size() + 1);
|
||
|
|
||
|
mdID = ModuleDesc.ID();
|
||
|
isInterface = ModuleDesc.isInterface();
|
||
|
}
|
||
|
|
||
|
Module::~Module()
|
||
|
{
|
||
|
arts_debug("hide...");
|
||
|
hide();
|
||
|
arts_debug("sdfmd...");
|
||
|
list<ModulePort *>::iterator i;
|
||
|
|
||
|
for(i = inports.begin(); i != inports.end(); ++i) delete *i;
|
||
|
inports.clear();
|
||
|
|
||
|
for(i = outports.begin(); i != outports.end(); ++i) delete *i;
|
||
|
outports.clear();
|
||
|
|
||
|
StructureDesc.freeModuleDesc(ModuleDesc);
|
||
|
arts_debug("ok...");
|
||
|
delete _pixmap;
|
||
|
}
|
||
|
|
||
|
bool Module::moveInternal(int x, int y)
|
||
|
{
|
||
|
return ModuleDesc.moveTo(x, y);
|
||
|
}
|
||
|
|
||
|
int Module::width() const
|
||
|
{
|
||
|
return _width;
|
||
|
}
|
||
|
|
||
|
int Module::height() const
|
||
|
{
|
||
|
return _height;
|
||
|
}
|
||
|
|
||
|
StructureComponent::ComponentType Module::type()
|
||
|
{
|
||
|
return ctModule;
|
||
|
}
|
||
|
|
||
|
bool Module::drawNeedsBackground(int segment)
|
||
|
{
|
||
|
return (segment == 0);
|
||
|
}
|
||
|
|
||
|
void Module::drawSegment(QPainter *p, int cellsize, int segment)
|
||
|
{
|
||
|
int border = cellsize / 10; // for the logo
|
||
|
int ltop = (cellsize - border)/2;
|
||
|
int lbot = (cellsize + border)/2;
|
||
|
|
||
|
QColor mcolor(43, 43, 168);
|
||
|
QColor mcolorlight(164, 176, 242);
|
||
|
|
||
|
if(isInterface)
|
||
|
{
|
||
|
mcolor = QColor(100, 100, 100);
|
||
|
mcolorlight = QColor(160, 160, 160);
|
||
|
}
|
||
|
QColorGroup g( Qt::white, Qt::blue, mcolorlight, mcolor.dark(), mcolor,
|
||
|
Qt::black, Qt::black );
|
||
|
QBrush fill( mcolor );
|
||
|
QPen textpen(QColor(255, 255, 180), 1);
|
||
|
|
||
|
if(segment == 0)
|
||
|
{
|
||
|
qDrawShadePanel(p, border, border, cellsize - 2*border + 1, cellsize - 2*border + 1,
|
||
|
g, false, 1, &fill);
|
||
|
p->fillRect(cellsize - border - 1, ltop, cellsize, lbot - ltop + 1, fill);
|
||
|
p->setPen(g.light());
|
||
|
p->drawLine(cellsize - border, ltop - 1, cellsize, ltop - 1);
|
||
|
p->setPen(g.dark());
|
||
|
p->drawLine(cellsize - border, lbot + 1, cellsize, lbot + 1);
|
||
|
if(_pixmap)
|
||
|
{
|
||
|
int destsize = (cellsize - 4*border);
|
||
|
float sx = (float)destsize/(float)_pixmap->width();
|
||
|
float sy = (float)destsize/(float)_pixmap->height();
|
||
|
|
||
|
QWMatrix matrix;
|
||
|
matrix.scale(sx, sy);
|
||
|
QPixmap pmscaled = _pixmap->xForm(matrix);
|
||
|
p->drawPixmap(border*2, border*2, pmscaled);
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
p->fillRect(0, 0, cellsize, cellsize, fill);
|
||
|
|
||
|
/*
|
||
|
* take care of the bevel lines around the module
|
||
|
*/
|
||
|
|
||
|
p->setPen(g.light());
|
||
|
p->drawLine(0, 0, cellsize - 1, 0);
|
||
|
if(segment < 2)
|
||
|
p->drawLine(0, 0, 0, cellsize - 1);
|
||
|
|
||
|
p->setPen(g.dark());
|
||
|
p->drawLine(cellsize - 1, cellsize - 1, 0, cellsize - 1);
|
||
|
if(segment == 0 || segment == width() - 1)
|
||
|
p->drawLine(cellsize - 1, cellsize - 1, cellsize - 1, 0);
|
||
|
|
||
|
/*
|
||
|
* now draw the ports
|
||
|
*/
|
||
|
int direction;
|
||
|
|
||
|
for(direction = 0;direction < 2; direction++)
|
||
|
{
|
||
|
ModulePort *port = findPort(segment, direction);
|
||
|
|
||
|
if(port)
|
||
|
{
|
||
|
int border = cellsize/7;
|
||
|
int textwidth;
|
||
|
QString label = DrawUtils::cropText(p, port->description,
|
||
|
cellsize/2, textwidth);
|
||
|
|
||
|
QBrush pbrush(port->color(isInterface));
|
||
|
|
||
|
port->clickrect = QRect(border, direction * cellsize/2 + border,
|
||
|
cellsize/2 - 2*border, cellsize/2 - 2*border);
|
||
|
qDrawShadePanel(p, port->clickrect, g, port->down(), 2, &pbrush);
|
||
|
|
||
|
#if 0
|
||
|
QBrush fillport(fill);
|
||
|
if(port->isinitarg)
|
||
|
{
|
||
|
fillport = QColor(128, 128, 128);
|
||
|
}
|
||
|
|
||
|
if(port->selected)
|
||
|
{
|
||
|
QBrush fillorange(QColor(255, 165, 0));
|
||
|
qDrawShadePanel(p, port->clickrect, g, true, 2, &fillorange);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(port->PortDesc->isConnected())
|
||
|
{
|
||
|
qDrawShadePanel(p, port->clickrect, g, true, 2, &fillport);
|
||
|
}
|
||
|
else if(port->PortDesc->hasValue())
|
||
|
{
|
||
|
QBrush fillp(QColor(100, 100, 255));
|
||
|
if(port->isinitarg)
|
||
|
{
|
||
|
fillp = QColor(180, 180, 180);
|
||
|
}
|
||
|
qDrawShadePanel(p, port->clickrect, g, true, 2, &fillp);
|
||
|
}
|
||
|
else // not connected and no value();
|
||
|
qDrawShadePanel(p, port->clickrect, g, false, 2, &fillport);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
p->setPen(textpen);
|
||
|
p->drawText((cellsize - border)/2,
|
||
|
(1 + direction) * (cellsize/2) - border, label);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* if it was the rightmost part of the module, it has the module name
|
||
|
* and the connection to the logo as well
|
||
|
*/
|
||
|
|
||
|
if(segment == 1)
|
||
|
{
|
||
|
// object type label
|
||
|
int textwidth;
|
||
|
QString label = DrawUtils::cropText(p, _name, cellsize - 4, textwidth);
|
||
|
|
||
|
p->setPen(textpen);
|
||
|
p->fillRect(1, cellsize - 16, textwidth + 7, 15, QBrush(g.dark()));
|
||
|
p->drawText(4, cellsize - 5, label);
|
||
|
|
||
|
// logo connection
|
||
|
p->setPen(mcolor);
|
||
|
p->drawLine(0, ltop, 0, lbot);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* when selected, draw a line of white dots around the module
|
||
|
*/
|
||
|
|
||
|
if(selected())
|
||
|
{
|
||
|
QPen pen(Qt::white, 1, Qt::DotLine);
|
||
|
|
||
|
p->setPen(pen);
|
||
|
p->drawLine(0, 0, cellsize - 1, 0);
|
||
|
p->drawLine(0, cellsize - 1, cellsize - 1, cellsize - 1);
|
||
|
if(segment == 1)
|
||
|
p->drawLine(0, 0, 0, cellsize - 1);
|
||
|
if(segment == _width - 1)
|
||
|
p->drawLine(cellsize - 1, 0, cellsize - 1, cellsize - 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ModulePort *Module::findPort(int xoffset, int direction)
|
||
|
{
|
||
|
list<ModulePort *>*ports;
|
||
|
list<ModulePort *>::iterator i;
|
||
|
|
||
|
long n;
|
||
|
|
||
|
if(direction == 0) ports = &inports; else ports = &outports;
|
||
|
|
||
|
i = ports->begin();
|
||
|
n = xoffset - 1 - direction;
|
||
|
|
||
|
if(n < (long)ports->size() && n >= 0)
|
||
|
{
|
||
|
while(n > 0) { n--; i++; }
|
||
|
return (*i);
|
||
|
}
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
ModulePort *Module::portAt(int segment, int x, int y)
|
||
|
{
|
||
|
for(int direction = 0; direction < 2; direction++)
|
||
|
{
|
||
|
ModulePort *port = findPort(segment, direction);
|
||
|
if(port)
|
||
|
{
|
||
|
QPoint clickpoint(x, y);
|
||
|
if(port->clickrect.contains(clickpoint)) return port;
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void Module::dumpPorts(list<ModulePort *>& ports)
|
||
|
{
|
||
|
list<ModulePort *>::iterator i;
|
||
|
for(i = inports.begin(); i != inports.end(); ++i) ports.push_back(*i);
|
||
|
for(i = outports.begin(); i != outports.end(); ++i) ports.push_back(*i);
|
||
|
}
|
||
|
|
||
|
QPixmap *Module::pixmap()
|
||
|
{
|
||
|
return _pixmap;
|
||
|
}
|
||
|
|
||
|
QString Module::name()
|
||
|
{
|
||
|
return _name;
|
||
|
}
|
||
|
|
||
|
// vim: sw=4 ts=4 noet
|