supernova: align wire buffers by cache-line boundaries
[supercollider.git] / QtCollider / Slot.cpp
blob121cbf5a4ef33074a9b92a5d2de96a344de1b04c
1 /************************************************************************
3 * Copyright 2010 Jakob Leben (jakob.leben@gmail.com)
5 * This file is part of SuperCollider Qt GUI.
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ************************************************************************/
22 #include "Slot.h"
23 #include "QObjectProxy.h"
24 #include "Common.h"
25 #include "primitives/prim_QPalette.hpp"
27 #include <PyrObject.h>
28 #include <PyrKernel.h>
29 #include <GC.h>
30 #include <VMGlobals.h>
32 #include <QPalette>
33 #include <QWidget>
34 #include <QVector>
36 #include <qmath.h>
38 using namespace QtCollider;
40 static QPalette::ColorRole paletteColorRoles[] = {
41 QPalette::Window,
42 QPalette::WindowText,
43 QPalette::Button,
44 QPalette::ButtonText,
45 QPalette::Base,
46 QPalette::Text,
47 QPalette::Highlight,
48 QPalette::HighlightedText,
51 void Slot::setRect( PyrSlot *slot, const QRectF &r )
53 PyrObject *obj = instantiateObject( gMainVMGlobals->gc, class_Rect, 0, true, true );
54 SetObject( slot, obj );
56 PyrSlot *slots = obj->slots;
57 SetFloat( slots+0, r.x() );
58 SetFloat( slots+1, r.y() );
59 SetFloat( slots+2, r.width() );
60 SetFloat( slots+3, r.height() );
63 void Slot::setPoint( PyrSlot *slot, const QPointF &pt )
65 PyrObject *obj = instantiateObject( gMainVMGlobals->gc, class_Point, 0, true, true );
66 SetObject( slot, obj );
68 PyrSlot *slots = obj->slots;
69 SetFloat( slots+0, pt.x() );
70 SetFloat( slots+1, pt.y() );
73 void Slot::setSize( PyrSlot *slot, const QSizeF &sz )
75 PyrObject *obj = instantiateObject( gMainVMGlobals->gc, class_Size, 0, true, true );
76 SetObject( slot, obj );
78 PyrSlot *slots = obj->slots;
79 SetFloat( slots+0, sz.width() );
80 SetFloat( slots+1, sz.height() );
83 void Slot::setString( PyrSlot *slot, const QString& arg )
85 PyrString *str = newPyrString( gMainVMGlobals->gc,
86 arg.toStdString().c_str(), 0, true );
87 SetObject( slot, str );
90 void Slot::setColor( PyrSlot *slot, const QColor &c )
92 PyrObject *obj = instantiateObject( gMainVMGlobals->gc, class_Color, 0, true, true );
93 SetObject( slot, obj );
95 PyrSlot *slots = obj->slots;
96 SetFloat( slots+0, c.red() / 255.0 );
97 SetFloat( slots+1, c.green() / 255.0 );
98 SetFloat( slots+2, c.blue() / 255.0 );
99 SetFloat( slots+3, c.alpha() / 255.0 );
102 void Slot::setPalette( PyrSlot *slot, const QPalette &plt )
104 PyrGC *gc = gMainVMGlobals->gc;
105 PyrObject *obj = instantiateObject( gc, class_QPalette, 0, true, true );
106 SetObject( slot, obj );
108 QPalette_Init( gMainVMGlobals, obj, plt );
111 void Slot::setQObject( PyrSlot *s, QObject *o )
113 if( !o ) {
114 SetNil(s);
115 return;
118 QObjectProxy *proxy = QObjectProxy::fromObject(o);
119 if( proxy && proxy->scObject() )
120 SetObject( s, proxy->scObject() );
121 else
122 SetNil( s );
125 void Slot::setTreeWidgetItem( PyrSlot *s, const SafePtr<QcTreeWidget::Item> & itemPtr )
127 PyrObject *obj = instantiateObject( gMainVMGlobals->gc, class_QTreeViewItem, 0, true, true );
128 QcTreeWidget::Item::initialize( gMainVMGlobals, obj, itemPtr );
129 SetObject( s, obj );
132 void Slot::setVariantList( PyrSlot *slot, const VariantList& varList )
134 VMGlobals *g = gMainVMGlobals;
136 int count = varList.data.count();
138 PyrObject *array = newPyrArray( g->gc, count, 0, true );
139 SetObject( slot, array );
141 int i;
142 PyrSlot *s = array->slots;
143 for( i = 0; i < count; ++i, ++s ) {
144 if( !Slot::setVariant( s, varList.data[i] ) ) {
145 qcDebugMsg(1, "WARNING: Could not set one slot of array" );
147 array->size++;
148 g->gc->GCWrite( array, s );
152 template<typename numeric_type>
153 static void setNumeric( PyrSlot *, numeric_type );
156 template<> inline
157 void setNumeric<double>( PyrSlot *s, double val )
159 SetFloat( s, val );
162 template<> inline
163 void setNumeric<int>( PyrSlot *s, int val )
165 SetInt( s, val );
168 template<typename numeric_type>
169 static void setNumericVector( PyrSlot *slot, const QVector<numeric_type> & vec )
171 VMGlobals *g = gMainVMGlobals;
173 int count = vec.count();
175 PyrObject *array = newPyrArray( g->gc, count, 0, true );
176 SetObject( slot, array );
178 PyrSlot *s = array->slots;
179 Q_FOREACH( numeric_type val, vec ) {
180 setNumeric<numeric_type>( s, val );
181 ++array->size;
182 ++s;
186 bool Slot::setVariant( PyrSlot *slot, const QVariant &val )
188 bool b_val;
189 int type = val.userType();
191 switch( type ) {
192 case QMetaType::Bool:
193 b_val = val.toBool();
194 if( b_val ) SetTrue( slot );
195 else SetFalse( slot );
196 break;
198 case QMetaType::QPoint:
199 case QMetaType::QPointF:
200 Slot::setPoint( slot, val.toPointF() );
201 break;
203 case QMetaType::QSize:
204 case QMetaType::QSizeF:
205 Slot::setSize( slot, val.toSizeF() );
206 break;
208 case QMetaType::QRect:
209 case QMetaType::QRectF:
210 Slot::setRect( slot, val.toRectF() );
211 break;
213 case QMetaType::QString:
214 Slot::setString( slot, val.toString() );
215 break;
217 case QMetaType::QColor:
218 Slot::setColor( slot, val.value<QColor>() );
219 break;
221 case QMetaType::QPalette:
222 Slot::setPalette( slot, val.value<QPalette>() );
223 break;
225 case QMetaType::Float:
226 case QMetaType::Double:
227 SetFloat( slot, val.value<double>() );
228 break;
230 case QMetaType::Int:
231 SetInt( slot, val.toInt() );
232 break;
234 case QMetaType::QObjectStar:
235 Slot::setQObject( slot, val.value<QObject*>() );
236 break;
238 case QMetaType::QWidgetStar:
239 Slot::setQObject( slot, val.value<QWidget*>() );
240 break;
242 case QMetaType::Void:
243 SetNil( slot );
244 break;
246 default:
247 if( type == qMetaTypeId<PyrObject*>() ) {
248 SetObject( slot, val.value<PyrObject*>() );
250 else if( type == qMetaTypeId<VariantList>() ) {
251 Slot::setVariantList( slot, val.value<VariantList>() );
253 else if( type == qMetaTypeId< QVector<double> >() ) {
254 setNumericVector( slot, val.value< QVector<double> >() );
256 else if( type == qMetaTypeId< QVector<int> >() ) {
257 setNumericVector( slot, val.value< QVector<int> >() );
259 else if( type == qMetaTypeId<QcTreeWidget::ItemPtr>() ) {
260 Slot::setTreeWidgetItem( slot, val.value< QtCollider::SafePtr<QcTreeWidget::Item> >() );
262 else {
263 qcErrorMsg( "the QVariant could not be interpreted!" );
264 return false;
268 return true;
271 bool Slot::toBool( PyrSlot *slot )
273 return IsTrue( slot );
276 int Slot::toInt( PyrSlot *slot )
278 int i;
279 if( slotIntVal( slot, &i ) ) return 0;
280 return i;
283 float Slot::toFloat( PyrSlot *slot )
285 float f;
286 if( slotFloatVal( slot, &f ) ) return 0.f;
287 return f;
290 double Slot::toDouble( PyrSlot *slot )
292 double d;
293 if( slotDoubleVal( slot, &d ) ) return 0.0;
294 return d;
297 QString Slot::toString( PyrSlot *slot )
299 if( IsSym(slot) ) {
300 return QString( slotRawSymbol(slot)->name );
302 else if( isKindOfSlot( slot, class_String ) ) {
303 int len = slotRawObject( slot )->size;
304 return QString::fromAscii( slotRawString(slot)->s, len );
306 return QString();
309 QPointF Slot::toPoint( PyrSlot *slot )
311 if( !isKindOfSlot( slot, class_Point ) ) {
312 return QPointF();
314 PyrSlot *slots = slotRawObject( slot )->slots;
315 float x, y;
316 int err;
317 err = slotFloatVal( slots+0, &x ); if( err ) return QPointF();
318 err = slotFloatVal( slots+1, &y ); if( err ) return QPointF();
319 return QPointF( x, y );
322 QRectF Slot::toRect( PyrSlot *slot )
324 if( !isKindOfSlot( slot, class_Rect ) ) {
325 return QRectF();
328 PyrSlot *slots = slotRawObject( slot )->slots;
329 float bounds[4];
330 for( int i=0; i<4; ++i )
332 int err = slotFloatVal(slots + i, &bounds[i]);
333 if( err ) return QRectF();
336 return QRectF( bounds[0], bounds[1], bounds[2], bounds[3] );
339 QSizeF Slot::toSize( PyrSlot *slot )
341 if( !isKindOfSlot( slot, class_Size ) ) {
342 return QSizeF();
345 PyrSlot *slots = slotRawObject( slot )->slots;
346 float w = 0.f, h = 0.f;
347 slotFloatVal( slots+0, &w );
348 slotFloatVal( slots+1, &h );
350 return QSizeF( w, h );
353 namespace QtCollider {
354 namespace Slot {
356 QColor asColor( PyrObject *obj )
358 PyrSlot *slots = obj->slots;
360 float r,g,b,a;
361 r = g = b = a = 0.f;
362 int err;
363 err = slotFloatVal(slots+0, &r);
364 if (err) return QColor();
365 err = slotFloatVal(slots+1, &g);
366 if (err) return QColor();
367 err = slotFloatVal(slots+2, &b);
368 if (err) return QColor();
369 err = slotFloatVal(slots+3, &a);
370 if (err) return QColor();
371 return QColor( r*255, g*255, b*255, a*255 );
377 QColor Slot::toColor( PyrSlot *slot )
379 if( NotObj(slot) ) return QColor();
381 PyrObject *obj = slotRawObject(slot);
382 PyrClass *klass = obj->classptr;
384 if( klass == class_Color )
385 return asColor(obj);
387 if( klass == SC_CLASS(Gradient) || klass == SC_CLASS(HiliteGradient) )
389 qcWarningMsg("WARNING: Gradient and HiliteGradient are not supported yet."
390 " Using the average gradient color instead.");
392 QColor c1( toColor(obj->slots+0) );
393 QColor c2( toColor(obj->slots+1) );
394 QColor mix( (c1.red() + c2.red()) / 2,
395 (c1.green() + c2.green()) / 2,
396 (c1.blue() + c2.blue()) / 2 );
397 return mix;
400 return QColor();
403 QFont Slot::toFont( PyrSlot *slot )
405 if( !isKindOfSlot( slot, class_QFont ) )
406 return QFont();
408 PyrSlot *slots = slotRawObject(slot)->slots;
410 QString family = Slot::toString( slots+0 );
411 float fSize = Slot::toFloat( slots+1 );
412 bool bold = IsTrue( slots+2 );
413 bool italic = IsTrue( slots+3 );
414 bool isPtSize = IsTrue( slots+4 );
416 QFont f;
418 if( !family.isEmpty() ) f.setFamily( family );
420 if( fSize > 0.f ) {
421 if( isPtSize ) {
422 f.setPointSizeF( fSize );
424 else {
425 int pixSize = ( fSize > 1.f ? qRound(fSize) : 1 );
426 f.setPixelSize( pixSize );
430 f.setBold( bold );
432 f.setItalic( italic );
434 return f;
437 QPalette Slot::toPalette( PyrSlot *slot )
439 if( !isKindOfSlot( slot, class_QPalette ) )
440 return QPalette();
442 QPalette *p = QPALETTE_FROM_OBJECT(slotRawObject(slot));
443 return *p;
446 VariantList Slot::toVariantList( PyrSlot *slot )
448 if( isKindOfSlot( slot, class_Array ) ) {
449 PyrObject *obj = slotRawObject( slot );
450 PyrSlot *slots = obj->slots;
451 int size = obj->size;
452 VariantList list;
453 for( int i = 0; i < size; ++i, ++slots )
454 list.data << Slot::toVariant( slots );
455 return list;
457 else if( isKindOfSlot( slot, class_SymbolArray ) ) {
458 PyrSymbolArray *symarray = slotRawSymbolArray( slot );
459 PyrSymbol **symbols = symarray->symbols;
460 int size = symarray->size;
461 VariantList list;
462 for( int i = 0; i < size; ++i, ++symbols )
463 list.data << QVariant( QString( (*symbols)->name) );
464 return list;
467 return VariantList();
470 #define WRONG_OBJECT_FORMAT false
472 template<typename DEST, typename ORIG>
473 inline static void copy( QVector<DEST> & dest, PyrSlot *orig, int size )
475 ORIG *array = (ORIG*) orig;
476 for( int i = 0; i < size; ++i )
477 dest << DEST(array[i]);
480 template<typename numeric_type>
481 static QVector<numeric_type> toNumericVector( PyrObject *obj )
483 int size = obj->size;
484 PyrSlot *slots = obj->slots;
486 QVector<numeric_type> vector;
487 vector.reserve(size);
489 switch (obj->obj_format) {
490 case obj_double:
491 copy<numeric_type, double>( vector, slots, size ); break;
492 case obj_float:
493 copy<numeric_type, float>( vector, slots, size ); break;
494 case obj_int32:
495 copy<numeric_type, int32>( vector, slots, size ); break;
496 case obj_int16:
497 copy<numeric_type, int16>( vector, slots, size ); break;
498 case obj_int8:
499 copy<numeric_type, int8>( vector, slots, size ); break;
500 default:
501 Q_ASSERT( WRONG_OBJECT_FORMAT );
504 return vector;
507 QObjectProxy* Slot::toObjectProxy( PyrSlot *slot )
509 if( !isKindOfSlot( slot, class_QObject ) ) return 0;
510 QObjectProxy *proxy = 0;
511 PyrSlot *proxySlot = slotRawObject( slot )->slots;
512 if( IsPtr( proxySlot ) ) proxy = (QObjectProxy*) slotRawPtr( proxySlot );
513 return proxy;
516 QcTreeWidget::ItemPtr Slot::toTreeWidgetItem( PyrSlot *slot )
518 if( !isKindOfSlot( slot, class_QTreeViewItem ) ) return QcTreeWidget::ItemPtr();
519 PyrSlot *ptrSlot = slotRawObject(slot)->slots+0;
520 if( IsPtr( ptrSlot ) ) {
521 QcTreeWidget::ItemPtr *safePtr = static_cast<QcTreeWidget::ItemPtr*>( slotRawPtr(ptrSlot) );
522 return *safePtr;
524 else {
525 return QcTreeWidget::ItemPtr();
529 QVariant Slot::toVariant( PyrSlot *slot )
531 QObjectProxy *proxy;
532 switch (GetTag(slot)) {
533 case tagChar :
534 case tagNil :
535 return QVariant();
536 case tagInt :
537 return QVariant( toInt(slot) );
538 case tagSym :
539 return QVariant( toString(slot) );
540 case tagFalse :
541 return QVariant( false );
542 case tagTrue :
543 return QVariant( true );
544 case tagObj :
546 PyrObject *obj = slotRawObject(slot);
547 PyrClass *klass = obj->classptr;
548 unsigned char format = obj->obj_format;
550 if( format == obj_double || format == obj_float )
551 return QVariant::fromValue< QVector<double> >( toNumericVector<double>(obj) );
553 else if( format == obj_int32 || format == obj_int16 || format == obj_int8 )
554 return QVariant::fromValue< QVector<int> >( toNumericVector<int>(obj) );
556 else if( isKindOfSlot( slot, class_String ) ) {
557 return QVariant( toString(slot) );
559 else if( isKindOfSlot( slot, class_Point ) ) {
560 return QVariant( toPoint( slot ) );
562 else if( isKindOfSlot( slot, class_Rect ) ) {
563 return QVariant( toRect(slot) );
565 else if( isKindOfSlot( slot, class_Size ) ) {
566 return QVariant( toSize(slot) );
568 else if( klass == class_Color ||
569 klass == SC_CLASS(Gradient) ||
570 klass == SC_CLASS(HiliteGradient) )
572 return QVariant::fromValue<QColor>( toColor(slot) );
574 else if( isKindOfSlot( slot, class_QFont ) ) {
575 return QVariant::fromValue<QFont>( toFont(slot) );
577 else if( isKindOfSlot( slot, class_QPalette ) ) {
578 return QVariant::fromValue<QPalette>( toPalette(slot) );
580 else if( isKindOfSlot( slot, class_QObject ) ) {
581 proxy = toObjectProxy(slot);
582 return QVariant::fromValue<QObjectProxy*>( proxy );
584 else if( isKindOfSlot( slot, class_Array ) || isKindOfSlot( slot, class_SymbolArray ) ) {
585 return QVariant::fromValue<VariantList>( toVariantList(slot) );
587 else if( isKindOfSlot( slot, class_QTreeViewItem ) ) {
588 return QVariant::fromValue<QcTreeWidget::ItemPtr>( toTreeWidgetItem(slot) );
590 else {
591 QString className = Slot::toString( &slotRawObject(slot)->classptr->name );
592 qcWarningMsg(QString("WARNING: Do not know how to use an instance of class '%1'").arg(className));
593 return QVariant();
596 default:
597 return QVariant( toDouble( slot ) );
601 using namespace Slot;
603 void QtCollider::Variant::setData( PyrSlot *slot )
605 QObjectProxy *proxy;
606 switch (GetTag(slot)) {
607 case tagChar :
608 case tagNil :
609 _type = QMetaType::Void;
610 _ptr = 0;
611 break;
612 case tagInt :
613 _type = QMetaType::Int;
614 _ptr = new int( toInt(slot) );
615 break;
616 case tagSym :
617 _type = QMetaType::QString;
618 _ptr = new QString( toString(slot) );
619 break;
620 case tagFalse :
621 _type = QMetaType::Bool;
622 _ptr = new bool( false );
623 break;
624 case tagTrue :
625 _type = QMetaType::Bool;
626 _ptr = new bool( true );
627 break;
628 case tagObj :
630 PyrObject *obj = slotRawObject(slot);
631 PyrClass *klass = obj->classptr;
632 unsigned char format = obj->obj_format;
634 if( format == obj_double || format == obj_float ) {
635 _type = qMetaTypeId< QVector<double> >();
636 _ptr = new QVector<double>( toNumericVector<double>(obj) );
638 else if( format == obj_int32 || format == obj_int16 || format == obj_int8 ) {
639 _type = qMetaTypeId< QVector<int> >();
640 _ptr = new QVector<int>( toNumericVector<int>(obj) );
642 else if( isKindOfSlot( slot, class_String ) ) {
643 _type = QMetaType::QString;
644 _ptr = new QString( toString(slot) );
646 else if( isKindOfSlot( slot, class_Point ) ) {
647 _type = QMetaType::QPointF;
648 _ptr = new QPointF( toPoint(slot) );
650 else if( isKindOfSlot( slot, class_Rect ) ) {
651 _type = QMetaType::QRectF;
652 _ptr = new QRectF( toRect(slot) );
654 else if( isKindOfSlot( slot, class_Size ) ) {
655 _type = QMetaType::QSizeF;
656 _ptr = new QSizeF( toSize(slot) );
658 else if( klass == class_Color ||
659 klass == SC_CLASS(Gradient) ||
660 klass == SC_CLASS(HiliteGradient) )
662 _type = QMetaType::QColor;
663 _ptr = new QColor( toColor(slot) );
665 else if( isKindOfSlot( slot, class_Array ) || isKindOfSlot( slot, class_SymbolArray ) ) {
666 _type = qMetaTypeId<VariantList>();
667 _ptr = new VariantList( toVariantList(slot) );
669 else if( isKindOfSlot( slot, class_QObject ) ) {
670 proxy = toObjectProxy(slot);
671 if( !proxy ) {
672 _type = QMetaType::Void;
673 _ptr = 0;
675 else {
676 _type = qMetaTypeId<QObjectProxy*>();
677 _ptr = new QObjectProxy*( proxy );
680 else if( isKindOfSlot( slot, class_QTreeViewItem ) ) {
681 _type = qMetaTypeId<QcTreeWidget::ItemPtr>();
682 _ptr = new QcTreeWidget::ItemPtr( toTreeWidgetItem(slot) );
684 else {
685 QString className = Slot::toString( &slotRawObject(slot)->classptr->name );
686 qcWarningMsg(QString("WARNING: Do not know how to use an instance of class '%1'").arg(className));
687 _type = QMetaType::Void;
688 _ptr = 0;
690 break;
692 default :
693 _type = QMetaType::Double;
694 _ptr = new double( toDouble(slot) );