00001
00024 #include "render_replaced.h"
00025 #include "render_root.h"
00026
00027 #include <assert.h>
00028 #include <qwidget.h>
00029 #include <qpainter.h>
00030 #include <qevent.h>
00031 #include <qapplication.h>
00032 #include <kglobalsettings.h>
00033
00034 #include "khtml_ext.h"
00035 #include "khtmlview.h"
00036 #include "xml/dom2_eventsimpl.h"
00037 #include "khtml_part.h"
00038 #include "xml/dom_docimpl.h"
00039 #include <kdebug.h>
00040
00041 using namespace khtml;
00042 using namespace DOM;
00043
00044
00045 RenderReplaced::RenderReplaced(DOM::NodeImpl* node)
00046 : RenderBox(node)
00047 {
00048
00049 setReplaced(true);
00050
00051 m_intrinsicWidth = 200;
00052 m_intrinsicHeight = 150;
00053 }
00054
00055 void RenderReplaced::paint( QPainter *p, int _x, int _y, int _w, int _h,
00056 int _tx, int _ty)
00057 {
00058
00059 if (style()->visibility() != VISIBLE || m_y <= -500000) return;
00060
00061 _tx += m_x;
00062 _ty += m_y;
00063
00064 if((_ty > _y + _h) || (_ty + m_height < _y)) return;
00065
00066
00067 bool clipped = false;
00068 if (style()->overflow()==OHIDDEN || (style()->position() == ABSOLUTE && style()->clipSpecified()) ) {
00069 calcClip(p, _tx, _ty);
00070 clipped = true;
00071 }
00072
00073 if(hasSpecialObjects()) paintBoxDecorations(p, _x, _y, _w, _h, _tx, _ty);
00074
00075 paintObject(p, _x, _y, _w, _h, _tx, _ty);
00076
00077
00078
00079 if ( clipped ) {
00080 p->restore();
00081 }
00082 }
00083
00084 void RenderReplaced::calcMinMaxWidth()
00085 {
00086 KHTMLAssert( !minMaxKnown());
00087
00088 #ifdef DEBUG_LAYOUT
00089 kdDebug( 6040 ) << "RenderReplaced::calcMinMaxWidth() known=" << minMaxKnown() << endl;
00090 #endif
00091
00092 int width = calcReplacedWidth();
00093
00094 if (!isWidget())
00095 width += paddingLeft() + paddingRight() + borderLeft() + borderRight();
00096
00097 if ( style()->width().isPercent() || style()->height().isPercent() ) {
00098 m_minWidth = 0;
00099 m_maxWidth = width;
00100 }
00101 else
00102 m_minWidth = m_maxWidth = width;
00103
00104 setMinMaxKnown();
00105 }
00106
00107 short RenderReplaced::lineHeight( bool ) const
00108 {
00109 return height()+marginTop()+marginBottom();
00110 }
00111
00112 short RenderReplaced::baselinePosition( bool ) const
00113 {
00114 return height()+marginTop()+marginBottom();
00115 }
00116
00117 void RenderReplaced::position(int x, int y, int, int, int, bool, bool, int)
00118 {
00119 m_x = x + marginLeft();
00120 m_y = y + marginTop();
00121 }
00122
00123
00124
00125 RenderWidget::RenderWidget(DOM::NodeImpl* node)
00126 : RenderReplaced(node)
00127 {
00128 m_widget = 0;
00129
00130 assert(node);
00131 m_view = node->getDocument()->view();
00132
00133
00134
00135
00136 ref();
00137 }
00138
00139 void RenderWidget::detach()
00140 {
00141 remove();
00142
00143 if ( m_widget ) {
00144 if ( m_view ) {
00145 m_view->setWidgetVisible(this, false);
00146 m_view->removeChild( m_widget );
00147 m_view = 0;
00148 }
00149
00150 m_widget->removeEventFilter( this );
00151 m_widget->setMouseTracking( false );
00152 }
00153 deref();
00154 }
00155
00156 RenderWidget::~RenderWidget()
00157 {
00158 KHTMLAssert( refCount() <= 0 );
00159
00160 if(m_widget) {
00161 m_widget->hide();
00162 m_widget->deleteLater();
00163 }
00164 }
00165
00166 class QWidgetResizeEvent : public QEvent
00167 {
00168 public:
00169 enum { Type = QEvent::User + 0xbee };
00170 QWidgetResizeEvent( int _w, int _h ) :
00171 QEvent( (QEvent::Type)Type ), w( _w ), h( _h ) {}
00172 int w;
00173 int h;
00174 };
00175
00176 void RenderWidget::resizeWidget( int w, int h )
00177 {
00178
00179 h = QMIN( h, 3072 );
00180 w = QMIN( w, 2000 );
00181
00182 if (m_widget->width() != w || m_widget->height() != h) {
00183 ref();
00184 element()->ref();
00185 QApplication::postEvent( this, new QWidgetResizeEvent( w, h ) );
00186 element()->deref();
00187 deref();
00188 }
00189 }
00190
00191 bool RenderWidget::event( QEvent *e )
00192 {
00193 if ( m_widget && (e->type() == (QEvent::Type)QWidgetResizeEvent::Type) ) {
00194 QWidgetResizeEvent *re = static_cast<QWidgetResizeEvent *>(e);
00195 m_widget->resize( re->w, re->h );
00196 }
00197 return true;
00198 }
00199
00200
00201 void RenderWidget::setQWidget(QWidget *widget)
00202 {
00203 if (widget != m_widget)
00204 {
00205 if (m_widget) {
00206 m_widget->removeEventFilter(this);
00207 disconnect( m_widget, SIGNAL( destroyed()), this, SLOT( slotWidgetDestructed()));
00208 delete m_widget;
00209 m_widget = 0;
00210 }
00211 m_widget = widget;
00212 if (m_widget) {
00213 connect( m_widget, SIGNAL( destroyed()), this, SLOT( slotWidgetDestructed()));
00214 m_widget->installEventFilter(this);
00215 if (m_widget->focusPolicy() > QWidget::StrongFocus)
00216 m_widget->setFocusPolicy(QWidget::StrongFocus);
00217
00218
00219 if (layouted()) {
00220
00221 resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
00222 m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
00223 }
00224 else
00225 setPos(xPos(), -500000);
00226 }
00227 m_view->setWidgetVisible(this, false);
00228 m_view->addChild( m_widget, 0, -500000);
00229 }
00230 }
00231
00232 void RenderWidget::layout( )
00233 {
00234 KHTMLAssert( !layouted() );
00235 KHTMLAssert( minMaxKnown() );
00236 if ( m_widget ) {
00237 resizeWidget( m_width-borderLeft()-borderRight()-paddingLeft()-paddingRight(),
00238 m_height-borderTop()-borderBottom()-paddingTop()-paddingBottom() );
00239 }
00240
00241 setLayouted();
00242 }
00243
00244 void RenderWidget::updateFromElement()
00245 {
00246 if (m_widget) {
00247 QColor color = style()->color();
00248 QColor backgroundColor = style()->backgroundColor();
00249
00250 if ( color.isValid() || backgroundColor.isValid() ) {
00251 QPalette pal(QApplication::palette(m_widget));
00252
00253 int contrast_ = KGlobalSettings::contrast();
00254 int highlightVal = 100 + (2*contrast_+4)*16/10;
00255 int lowlightVal = 100 + (2*contrast_+4)*10;
00256
00257 if (backgroundColor.isValid()) {
00258 for ( int i = 0; i < QPalette::NColorGroups; i++ ) {
00259 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Background, backgroundColor );
00260 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Light, backgroundColor.light(highlightVal) );
00261 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Dark, backgroundColor.dark(lowlightVal) );
00262 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Mid, backgroundColor.dark(120) );
00263 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Midlight, backgroundColor.light(110) );
00264 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Button, backgroundColor );
00265 pal.setColor( (QPalette::ColorGroup)i, QColorGroup::Base, backgroundColor );
00266 }
00267 }
00268 if ( color.isValid() ) {
00269 struct ColorSet {
00270 QPalette::ColorGroup cg;
00271 QColorGroup::ColorRole cr;
00272 };
00273 const struct ColorSet toSet [] = {
00274 { QPalette::Active, QColorGroup::Foreground },
00275 { QPalette::Active, QColorGroup::ButtonText },
00276 { QPalette::Active, QColorGroup::Text },
00277 { QPalette::Inactive, QColorGroup::Foreground },
00278 { QPalette::Inactive, QColorGroup::ButtonText },
00279 { QPalette::Inactive, QColorGroup::Text },
00280 { QPalette::Disabled,QColorGroup::ButtonText },
00281 { QPalette::NColorGroups, QColorGroup::NColorRoles },
00282 };
00283 const ColorSet *set = toSet;
00284 while( set->cg != QPalette::NColorGroups ) {
00285 pal.setColor( set->cg, set->cr, color );
00286 ++set;
00287 }
00288
00289 QColor disfg = color;
00290 int h, s, v;
00291 disfg.hsv( &h, &s, &v );
00292 if (v > 128)
00293
00294 disfg = disfg.dark(lowlightVal);
00295 else if (disfg != Qt::black)
00296
00297 disfg = disfg.light(highlightVal);
00298 else
00299
00300 disfg = Qt::darkGray;
00301 pal.setColor(QPalette::Disabled,QColorGroup::Foreground,disfg);
00302 }
00303
00304 m_widget->setPalette(pal);
00305 }
00306 else
00307 m_widget->unsetPalette();
00308 }
00309
00310 RenderReplaced::updateFromElement();
00311 }
00312
00313 void RenderWidget::slotWidgetDestructed()
00314 {
00315 m_widget = 0;
00316 }
00317
00318 void RenderWidget::setStyle(RenderStyle *_style)
00319 {
00320 RenderReplaced::setStyle(_style);
00321 if(m_widget)
00322 {
00323 m_widget->setFont(style()->font());
00324 if (style()->visibility() != VISIBLE) {
00325 m_widget->hide();
00326 }
00327 }
00328
00329
00330 setSpecialObjects(false);
00331 }
00332
00333 void RenderWidget::paintObject(QPainter* , int, int, int, int, int _tx, int _ty)
00334 {
00335 if (!m_widget || !m_view)
00336 return;
00337
00338 if (style()->visibility() != VISIBLE) {
00339 m_widget->hide();
00340 return;
00341 }
00342
00343
00344 if(isRelPositioned())
00345 relativePositionOffset(_tx, _ty);
00346
00347 int xPos = _tx+borderLeft()+paddingLeft();
00348 int yPos = _ty+borderTop()+paddingTop();
00349
00350 int childw = m_widget->width();
00351 int childh = m_widget->height();
00352 if ( (childw == 2000 || childh == 3072) && m_widget->inherits( "KHTMLView" ) ) {
00353 KHTMLView *vw = static_cast<KHTMLView *>(m_widget);
00354 int cy = m_view->contentsY();
00355 int ch = m_view->visibleHeight();
00356
00357
00358 int childx = m_view->childX( m_widget );
00359 int childy = m_view->childY( m_widget );
00360
00361 int xNew = xPos;
00362 int yNew = childy;
00363
00364
00365 if ( childh == 3072 ) {
00366 if ( cy + ch > childy + childh ) {
00367 yNew = cy + ( ch - childh )/2;
00368 } else if ( cy < childy ) {
00369 yNew = cy + ( ch - childh )/2;
00370 }
00371
00372 }
00373 yNew = QMIN( yNew, yPos + m_height - childh );
00374 yNew = QMAX( yNew, yPos );
00375 if ( yNew != childy || xNew != childx ) {
00376 if ( vw->contentsHeight() < yNew - yPos + childh )
00377 vw->resizeContents( vw->contentsWidth(), yNew - yPos + childh );
00378 vw->setContentsPos( xNew - xPos, yNew - yPos );
00379 }
00380 xPos = xNew;
00381 yPos = yNew;
00382 }
00383 m_view->setWidgetVisible(this, true);
00384 m_view->addChild(m_widget, xPos, yPos );
00385 m_widget->show();
00386 }
00387
00388 bool RenderWidget::eventFilter(QObject* , QEvent* e)
00389 {
00390 if ( !element() ) return true;
00391
00392 ref();
00393 element()->ref();
00394
00395 bool filtered = false;
00396
00397
00398 switch(e->type()) {
00399 case QEvent::FocusOut:
00400
00401
00402 if ( QFocusEvent::reason() != QFocusEvent::Popup )
00403 handleFocusOut();
00404 break;
00405 case QEvent::FocusIn:
00406
00407 element()->getDocument()->setFocusNode(element());
00408
00409
00410
00411
00412 break;
00413 case QEvent::MouseButtonPress:
00414 case QEvent::MouseButtonRelease:
00415 break;
00416 case QEvent::MouseButtonDblClick:
00417 break;
00418 case QEvent::MouseMove:
00419
00420
00421
00422
00423
00424
00425
00426
00427 break;
00428 case QEvent::Wheel:
00429
00430
00431
00432 if (qApp->focusWidget() != m_widget &&
00433 m_widget->focusPolicy() <= QWidget::StrongFocus) {
00434 static_cast<QWheelEvent*>(e)->ignore();
00435 QApplication::sendEvent(m_view, e);
00436 filtered = true;
00437 }
00438 break;
00439 case QEvent::KeyPress:
00440 case QEvent::KeyRelease:
00441 if (!element()->dispatchKeyEvent(static_cast<QKeyEvent*>(e)))
00442 filtered = true;
00443 break;
00444 default: break;
00445 };
00446
00447 element()->deref();
00448
00449
00450 if (hasOneRef())
00451 filtered = true;
00452 deref();
00453
00454 return filtered;
00455 }
00456
00457
00458 #include "render_replaced.moc"
00459