render_replaced.cpp Source File (khtml Library)

| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# render_replaced.cpp

    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" // ### remove dependency
    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     // init RenderObject attributes
    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     // not visible or nont even once layouted?
    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     // overflow: hidden
    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     // overflow: hidden
    00078     // restore clip region
    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     // a replaced element doesn't support being anonymous
    00130     assert(node);
    00131     m_view = node->getDocument()->view();
    00132
    00133     // this is no real reference counting, its just there
    00134     // to make sure that we're not deleted while we're recursed
    00135     // in an eventFilter of the widget
    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     // ugly hack to limit the maximum size of the widget (as X11 has problems i
    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             // if we're already layouted, apply the calculated space to the
    00218             // widget immediately
    00219             if (layouted()) {
    00220                 // ugly hack to limit the maximum size of the widget (as X11 has problems if it's bigger)
    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                     // dark bg, light fg - need a darker disabled fg
    00294                     disfg = disfg.dark(lowlightVal);
    00295                 else if (disfg != Qt::black)
    00296                     // light bg, dark fg - need a lighter disabled fg - but only if !black
    00297                     disfg = disfg.light(highlightVal);
    00298                 else
    00299                     // black fg - use darkgrey disabled fg
    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     // do not paint background or borders for widgets
    00330     setSpecialObjects(false);
    00331 }
    00332
    00333 void RenderWidget::paintObject(QPainter* /*p*/, 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     // add offset for relative positioning
    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         //      qDebug("cy=%d, ch=%d, childy=%d, childh=%d", cy, ch, childy, childh );
    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 //          qDebug("calculated yNew=%d", yNew);
    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* /*o*/, QEvent* e)
    00389 {
    00390     if ( !element() ) return true;
    00391
    00392     ref();
    00393     element()->ref();
    00394
    00395     bool filtered = false;
    00396
    00397     //kdDebug() << "RenderWidget::eventFilter type=" << e->type() << endl;
    00398     switch(e->type()) {
    00399     case QEvent::FocusOut:
    00400         // Don't count popup as a valid reason for losing the focus
    00401         // (example: opening the options of a select combobox shouldn't emit onblur)
    00402         if ( QFocusEvent::reason() != QFocusEvent::Popup )
    00403             handleFocusOut();
    00404         break;
    00405     case QEvent::FocusIn:
    00406         //kdDebug(6000) << "RenderWidget::eventFilter captures FocusIn" << endl;
    00407         element()->getDocument()->setFocusNode(element());
    00408 //         if ( isEditable() ) {
    00409 //             KHTMLPartBrowserExtension *ext = static_cast<KHTMLPartBrowserExtension *>( element()->view->part()->browserExtension() );
    00410 //             if ( ext )  ext->editableWidgetFocused( m_widget );
    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 //         int absX, absY;
    00421 //         absolutePosition(absX,absY);
    00422 //         QMouseEvent* _e = static_cast<QMouseEvent*>(e);
    00423 //         QMouseEvent e2(e->type(),QPoint(absX,absY)+_e->pos(),_e->button(),_e->state());
    00424 //         element()->dispatchMouseEvent(&e2);
    00425 //         // ### change cursor like in KHTMLView?
    00426 //     }
    00427     break;
    00428     case QEvent::Wheel:
    00429         // don't allow the widget to react to wheel event unless its
    00430         // currently focused. this avoids accidentally changing a select box
    00431         // or something while wheeling a webpage.
    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     // stop processing if the widget gets deleted, but continue in all other cases
    00450     if (hasOneRef())
    00451         filtered = true;
    00452     deref();
    00453
    00454     return filtered;
    00455 }
    00456
    00457
    00458 // -----------------------------------------------------------------------------
    00459
    00460 RenderReplacedFlow::RenderReplacedFlow(DOM::NodeImpl* node)
    00461     : RenderFlow(node)
    00462 {
    00463     assert(node);
    00464     m_intrinsicWidth = 100;
    00465     setReplaced( true );
    00466 }
    00467
    00468 void RenderReplacedFlow::calcMinMaxWidth()
    00469 {
    00470     KHTMLAssert( !minMaxKnown() );
    00471
    00472     RenderObject *r = firstChild();
    00473     short wi, maxw;
    00474     wi = maxw = 0;
    00475
    00476     while(r) {
    00477         if(r->isSpecial())
    00478         {
    00479             r = r->nextSibling();
    00480             continue;
    00481         }
    00482         if( !r->minMaxKnown() )
    00483              r->calcMinMaxWidth();
    00484         short childMaxWidth = r->maxWidth();
    00485         if( r->isInline() && r->childrenInline() )
    00486             wi = calcObjectWidth( r, wi );
    00487         else if( r->isInline() )
    00488             wi += r->maxWidth();
    00489         else
    00490             maxw = QMAX( maxw, childMaxWidth );
    00491         r = r->nextSibling();
    00492     }
    00493
    00494     maxw = QMAX( maxw, wi );
    00495
    00496     if ( style()->width().isPercent() || style()->height().isPercent() ) {
    00497          m_minWidth = 0;
    00498          m_maxWidth = maxw;
    00499     }
    00500     else
    00501          m_minWidth = m_maxWidth = maxw;
    00502
    00503     setIntrinsicWidth( maxw );
    00504     setMinMaxKnown();
    00505 }
    00506
    00507 short RenderReplacedFlow::calcObjectWidth( RenderObject *o, short width )
    00508 {
    00509     for( o = o->firstChild(); o; o = o->nextSibling() )
    00510     {
    00511         width = calcObjectWidth( o, width );
    00512         if( o->isInline() )
    00513             width += o->maxWidth();
    00514     }
    00515     return width;
    00516 }
    00517
    00518 #include "render_replaced.moc"
    00519

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:39 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001