Linux multi-monitor fullscreen support
[ryzomcore.git] / studio / src / plugins / gui_editor / expression_node.cpp
blob6beb97327c16615c0ff37c06bdaffb9500408853
1 // Ryzom Core Studio - GUI Editor Plugin
2 //
3 // Copyright (C) 2010-2014 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Affero General Public License as
7 // published by the Free Software Foundation, either version 3 of the
8 // License, or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU Affero General Public License for more details.
15 // You should have received a copy of the GNU Affero General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include "expression_node.h"
20 #include "expression_link.h"
21 #include <QPainter>
22 #include <QStyleOption>
24 struct NodeSlotInfo
26 // top-left
27 QPoint tl;
29 // text top-left
30 QPoint ttl;
32 // The text displayed
33 QString text;
35 // text width
36 qreal tw;
38 // text height
39 qreal th;
41 // width-height of the box
42 qreal wh;
45 class NodeSlot
47 public:
48 NodeSlot( const NodeSlotInfo &info )
50 m_info = info;
53 ~NodeSlot()
57 QPointF pos() const{
58 QPointF p;
59 p.setX( m_info.tl.x() + m_info.wh / 2.0 );
60 p.setY( m_info.tl.y() + m_info.wh / 2.0 );
62 return p;
65 void paint( QPainter *painter )
67 QBrush boxBrush;
68 QPen p;
70 boxBrush.setColor( Qt::black );
71 boxBrush.setStyle( Qt::SolidPattern );
72 p.setColor( Qt::black );
73 painter->setPen( p );
75 QRectF box;
76 QRectF tbox;
78 box.setTopLeft( m_info.tl );
79 box.setHeight( m_info.wh );
80 box.setWidth( m_info.wh );
82 painter->fillRect( box, boxBrush );
84 tbox.setTopLeft( m_info.ttl );
85 tbox.setHeight( m_info.th );
86 tbox.setWidth( m_info.tw );
88 painter->drawText( tbox, Qt::AlignRight, m_info.text );
91 QString text() const{ return m_info.text; }
92 void setText( const QString &text ){ m_info.text = text; }
94 private:
95 NodeSlotInfo m_info;
100 ExpressionNode::ExpressionNode( const QString &name, int slotCount, QGraphicsItem *parent ) :
101 QGraphicsItem( parent )
103 setFlags( QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsScenePositionChanges );
105 m_w = 100;
106 m_h = 100;
107 m_hh = 20.0;
109 m_variable = false;
110 m_isValue = false;
111 m_isRoot = false;
113 m_name = name;
115 if( slotCount > 3 )
116 m_h = m_h + 20.0 * ( slotCount - 3 );
118 createSlots( slotCount );
121 ExpressionNode::~ExpressionNode()
123 clearLinks();
124 clearSlots();
127 QRectF ExpressionNode::boundingRect() const
129 return QRectF( 0, 0, m_w, m_h );
132 void ExpressionNode::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
134 QBrush br;
135 QBrush boxBrush;
136 QPen p;
137 QColor c;
139 QRectF rect = boundingRect();
140 QRectF header = rect;
141 header.setHeight( m_hh );
143 // Draw filled rectangle, header
144 if( !m_isRoot )
146 c.setRed( 44 );
147 c.setGreen( 169 );
148 c.setBlue( 232 );
150 else
152 c.setRed( 255 );
153 c.setGreen( 0 );
154 c.setBlue( 0 );
156 br.setColor( c );
157 br.setStyle( Qt::SolidPattern );
158 p.setColor( c );
159 painter->setPen( p );
160 painter->fillRect( header, br );
162 // Draw header text
163 p.setColor( Qt::black );
164 painter->setPen( p );
165 painter->drawText( header, Qt::AlignCenter, m_name );
167 // Draw value if applicable
168 if( m_isValue )
170 QRectF vbox;
171 vbox.setTopLeft( QPoint( 0.0, 20.0 ) );
172 vbox.setWidth( header.width() );
173 vbox.setHeight( header.height() );
174 QPen vpen;
175 vpen.setColor( Qt::red );
176 painter->setPen( vpen );
177 painter->drawText( vbox, Qt::AlignCenter, m_value );
178 painter->setPen( p );
181 if( option->state & QStyle::State_Selected )
183 p.setStyle( Qt::DotLine );
184 p.setColor( Qt::red );
187 // Draw outline of the entire thing + header
188 painter->setPen( p );
189 painter->drawRect( rect );
190 painter->drawRect( header );
192 paintSlots( painter );
196 QPointF ExpressionNode::slotPos( int slot ) const
198 const NodeSlot *s = m_slots[ slot ];
199 QPointF sp = s->pos();
200 QPointF mp = pos();
202 mp += sp;
203 return mp;
206 void ExpressionNode::changeSlotCount( int count )
208 clearSlots();
209 clearLinks();
210 m_links.clear();
212 if( count <= 3 )
213 m_h = 100.0;
214 else
215 m_h = 100.0 + 20.0 * ( count - 3 );
217 createSlots( count );
219 update();
222 void ExpressionNode::clearSlots()
224 qDeleteAll( m_slots );
225 m_slots.clear();
228 bool ExpressionNode::slotEmpty( int slot ) const
230 if( m_links[ 0 ] == NULL )
231 return true;
232 else
233 return false;
236 void ExpressionNode::getSlots( QList< SlotInfo > &l )
238 SlotInfo info;
240 for( int i = 0; i < m_slots.count(); i++ )
242 if( m_links[ i ] != NULL )
243 continue;
245 info.name = m_slots[ i ]->text();
246 info.slot = i;
247 l.push_back( info );
251 void ExpressionNode::setLink( ExpressionLink *link, int slot )
253 m_links[ slot ] = link;
256 ExpressionLink* ExpressionNode::link( int slot ) const
258 return m_links[ slot ];
261 void ExpressionNode::setSlotNames( const QList< QString > &l )
263 int c = l.count();
264 for( int i = 0; i < c; i++ )
266 // "Out" slot is at position 0, so set the names with an offset of 1
267 m_slots[ i + 1 ]->setText( l[ i ] );
271 void ExpressionNode::setValue( const QString &value )
273 m_value = value;
275 int c = m_value.count();
276 if( c < 15 )
277 m_w = 100.0;
278 else
279 m_w = m_w + ( 100.0 / 15.0 ) * ( c - 15.0 );
281 update();
284 void ExpressionNode::setRoot( bool b )
286 m_isRoot = b;
287 update();
290 QString ExpressionNode::build() const
292 QString result;
294 if( isValue() )
295 return m_value;
297 QStringList l = m_name.split( ' ' );
298 result = l[ 0 ];
300 int c = m_links.count();
301 if( c == 1 )
303 result += "()";
304 return result;
307 result += "( ";
309 for( int i = 1; i < c; i++ )
311 ExpressionLink *link = m_links[ i ];
312 if( link == NULL )
313 continue;
315 ExpressionNode *node = NULL;
317 if( link->from() == this )
318 node = link->to();
319 else
320 node = link->from();
322 result += node->build();
324 if( i != ( c - 1 ) )
325 result += ", ";
328 result += " )";
329 return result;
332 QVariant ExpressionNode::itemChange( GraphicsItemChange change, const QVariant &value )
334 if( change == ItemScenePositionHasChanged )
336 onNodeMove();
339 return QGraphicsItem::itemChange( change, value );
342 void ExpressionNode::onNodeMove()
344 for( int i = 0; i < m_links.count(); i++ )
346 ExpressionLink *link = m_links[ i ];
347 if( link == NULL )
348 continue;
350 link->nodeMoved();
354 void ExpressionNode::createSlots( int count)
356 // Out nodes
357 m_links.push_back( NULL );
359 for( int i = 0; i < count; i++ )
360 m_links.push_back( NULL );
362 // First create the "Out" slot
363 NodeSlotInfo info;
364 info.tw = 25.0;
365 info.th = 12.0;
366 info.wh = 10.0;
368 qreal x = 0.0;
369 qreal y = m_h * 0.5;
370 qreal tx = info.wh;
371 qreal ty = m_h * 0.5 - 2;
373 info.tl = QPoint( x, y );
374 info.ttl = QPoint( tx, ty );
375 info.text = "Out";
377 m_slots.push_back( new NodeSlot( info ) );
379 // Then the rest of them
380 for( int i = 0; i < count; i++ )
382 x = m_w - info.wh;
383 y = 30 + i * 20.0;
384 tx = x - 5 - info.tw;
385 ty = y - 2;
387 info.tl = QPoint( x, y );
388 info.ttl = QPoint( tx, ty );
389 info.text = QString( 'A' + i );
391 m_slots.push_back( new NodeSlot( info ) );
395 void ExpressionNode::paintSlots( QPainter *painter )
397 for( int i = 0; i < m_slots.count(); i++ )
399 NodeSlot *slot = m_slots[ i ];
400 slot->paint( painter );
405 void ExpressionNode::clearLinks()
407 for( int i = 0; i < m_links.count(); i++ )
409 ExpressionLink *link = m_links[ i ];
410 if( link == NULL )
411 continue;
413 link->unlink();