# qwt_slider.cpp

    00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
    00002  * Qwt Widget Library
    00003  * Copyright (C) 1997   Josef Wilgen
    00004  * Copyright (C) 2002   Uwe Rathmann
    00005  *
    00006  * This library is free software; you can redistribute it and/or
    00007  * modify it under the terms of the Qwt License, Version 1.0
    00008  *****************************************************************************/
    00009
    00010 // vim: expandtab
    00011
    00012 #include <math.h>
    00013 #include <qevent.h>
    00014 #include <qdrawutil.h>
    00015 #include <qpainter.h>
    00016 #include <qwt_painter.h>
    00017 #include "qwt_paint_buffer.h"
    00018 #include "qwt_scale_draw.h"
    00019 #include "qwt_scale_map.h"
    00020 #include "qwt_slider.h"
    00021
    00022 class QwtSlider::PrivateData
    00023 {
    00024 public:
    00025     QRect sliderRect;
    00026
    00027     int thumbLength;
    00028     int thumbWidth;
    00029     int borderWidth;
    00030     int scaleDist;
    00031     int xMargin;
    00032     int yMargin;
    00033
    00034     QwtSlider::ScalePos scalePos;
    00035     QwtSlider::BGSTYLE bgStyle;
    00036
    00037     /*
    00038       Scale and values might have different maps. This is
    00039       confusing and I can't see strong arguments for such
    00040       a feature. TODO ...
    00041      */
    00042     QwtScaleMap map; // linear map
    00043     mutable QSize sizeHintCache;
    00044 };
    00045
    00064 QwtSlider::QwtSlider(QWidget *parent,
    00065         Qt::Orientation orientation, ScalePos scalePos, BGSTYLE bgStyle):
    00066     QwtAbstractSlider(orientation, parent)
    00067 {
    00068     initSlider(orientation, scalePos, bgStyle);
    00069 }
    00070
    00071 #if QT_VERSION < 0x040000
    00072
    00081 QwtSlider::QwtSlider(QWidget *parent, const char* name):
    00082     QwtAbstractSlider(Qt::Horizontal, parent)
    00083 {
    00084     setName(name);
    00085     initSlider(Qt::Horizontal, NoScale, BgTrough);
    00086 }
    00087 #endif
    00088
    00089 void QwtSlider::initSlider(Qt::Orientation orientation,
    00090     ScalePos scalePos, BGSTYLE bgStyle)
    00091 {
    00092     if (orientation == Qt::Vertical)
    00093         setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
    00094     else
    00095         setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    00096
    00097 #if QT_VERSION >= 0x040000
    00098     setAttribute(Qt::WA_WState_OwnSizePolicy, false);
    00099 #else
    00100     clearWState( WState_OwnSizePolicy );
    00101 #endif
    00102
    00103
    00104 #if QT_VERSION < 0x040000
    00105     setWFlags(Qt::WNoAutoErase);
    00106 #endif
    00107
    00108     d_data = new QwtSlider::PrivateData;
    00109
    00110     d_data->borderWidth = 2;
    00111     d_data->scaleDist = 4;
    00112     d_data->scalePos = scalePos;
    00113     d_data->xMargin = 0;
    00114     d_data->yMargin = 0;
    00115     d_data->bgStyle = bgStyle;
    00116
    00117     if (bgStyle == BgSlot)
    00118     {
    00119         d_data->thumbLength = 16;
    00120         d_data->thumbWidth = 30;
    00121     }
    00122     else
    00123     {
    00124         d_data->thumbLength = 31;
    00125         d_data->thumbWidth = 16;
    00126     }
    00127
    00128     d_data->sliderRect.setRect(0,0,8,8);
    00129
    00130     QwtScaleDraw::Alignment align;
    00131     if ( orientation == Qt::Vertical )
    00132     {
    00133         // enforce a valid combination of scale position and orientation
    00134         if ((d_data->scalePos == BottomScale) || (d_data->scalePos == TopScale))
    00135             d_data->scalePos = NoScale;
    00136         // adopt the policy of layoutSlider (NoScale lays out like Left)
    00137         if (d_data->scalePos == RightScale)
    00138            align = QwtScaleDraw::RightScale;
    00139         else
    00140            align = QwtScaleDraw::LeftScale;
    00141     }
    00142     else
    00143     {
    00144         // enforce a valid combination of scale position and orientation
    00145         if ((d_data->scalePos == LeftScale) || (d_data->scalePos == RightScale))
    00146             d_data->scalePos = NoScale;
    00147         // adopt the policy of layoutSlider (NoScale lays out like Bottom)
    00148         if (d_data->scalePos == TopScale)
    00149            align = QwtScaleDraw::TopScale;
    00150         else
    00151            align = QwtScaleDraw::BottomScale;
    00152     }
    00153
    00154     scaleDraw()->setAlignment(align);
    00155     scaleDraw()->setLength(100);
    00156
    00157     setRange(0.0, 100.0, 1.0);
    00158     setValue(0.0);
    00159 }
    00160
    00161 QwtSlider::~QwtSlider()
    00162 {
    00163     delete d_data;
    00164 }
    00165
    00174 void QwtSlider::setOrientation(Qt::Orientation o)
    00175 {
    00176     if ( o == orientation() )
    00177         return;
    00178
    00179     if (o == Qt::Horizontal)
    00180     {
    00181         if ((d_data->scalePos == LeftScale) || (d_data->scalePos == RightScale))
    00182             d_data->scalePos = NoScale;
    00183     }
    00184     else // if (o == Qt::Vertical)
    00185     {
    00186         if ((d_data->scalePos == BottomScale) || (d_data->scalePos == TopScale))
    00187             d_data->scalePos = NoScale;
    00188     }
    00189
    00190 #if QT_VERSION >= 0x040000
    00191     if ( !testAttribute(Qt::WA_WState_OwnSizePolicy) )
    00192 #else
    00193     if ( !testWState( WState_OwnSizePolicy ) )
    00194 #endif
    00195     {
    00196         QSizePolicy sp = sizePolicy();
    00197         sp.transpose();
    00198         setSizePolicy(sp);
    00199
    00200 #if QT_VERSION >= 0x040000
    00201         setAttribute(Qt::WA_WState_OwnSizePolicy, false);
    00202 #else
    00203         clearWState( WState_OwnSizePolicy );
    00204 #endif
    00205     }
    00206
    00207     QwtAbstractSlider::setOrientation(o);
    00208     layoutSlider();
    00209 }
    00210
    00224 void QwtSlider::setScalePosition(ScalePos s)
    00225 {
    00226     d_data->scalePos = s;
    00227     if ((s == BottomScale) || (s == TopScale))
    00228         setOrientation(Qt::Horizontal);
    00229     else if ((s == LeftScale) || (s == RightScale))
    00230         setOrientation(Qt::Vertical);
    00231     else
    00232         layoutSlider();
    00233 }
    00234
    00236 QwtSlider::ScalePos QwtSlider::scalePosition() const
    00237 {
    00238     return d_data->scalePos;
    00239 }
    00240
    00245 void QwtSlider::setBorderWidth(int bd)
    00246 {
    00247     if ( bd < 0 )
    00248         bd = 0;
    00249
    00250     if ( bd != d_data->borderWidth )
    00251     {
    00252         d_data->borderWidth = bd;
    00253         layoutSlider();
    00254     }
    00255 }
    00256
    00261 void QwtSlider::setThumbLength(int thumbLength)
    00262 {
    00263     if ( thumbLength < 8 )
    00264         thumbLength = 8;
    00265
    00266     if ( thumbLength != d_data->thumbLength )
    00267     {
    00268         d_data->thumbLength = thumbLength;
    00269         layoutSlider();
    00270     }
    00271 }
    00272
    00277 void QwtSlider::setThumbWidth(int w)
    00278 {
    00279     if ( w < 4 )
    00280         w = 4;
    00281
    00282     if ( d_data->thumbWidth != w )
    00283     {
    00284         d_data->thumbWidth = w;
    00285         layoutSlider();
    00286     }
    00287 }
    00288
    00289 void QwtSlider::setScaleDraw(QwtScaleDraw *scaleDraw)
    00290 {
    00291     setAbstractScaleDraw(scaleDraw);
    00292 }
    00293
    00294 const QwtScaleDraw *QwtSlider::scaleDraw() const
    00295 {
    00296     return (QwtScaleDraw *)abstractScaleDraw();
    00297 }
    00298
    00299 QwtScaleDraw *QwtSlider::scaleDraw()
    00300 {
    00301     return (QwtScaleDraw *)abstractScaleDraw();
    00302 }
    00303
    00305 void QwtSlider::scaleChange()
    00306 {
    00307     layoutSlider();
    00308 }
    00309
    00310
    00312 void QwtSlider::fontChange(const QFont &f)
    00313 {
    00314     QwtAbstractSlider::fontChange( f );
    00315     layoutSlider();
    00316 }
    00317
    00319 void QwtSlider::drawSlider(QPainter *p, const QRect &r)
    00320 {
    00321     QRect cr(r);
    00322
    00323     if (d_data->bgStyle & BgTrough)
    00324     {
    00325         qDrawShadePanel(p, r.x(), r.y(),
    00326             r.width(), r.height(),
    00327 #if QT_VERSION < 0x040000
    00328             colorGroup(),
    00329 #else
    00330             palette(),
    00331 #endif
    00332             true, d_data->borderWidth,0);
    00333
    00334         cr.setRect(r.x() + d_data->borderWidth,
    00335             r.y() + d_data->borderWidth,
    00336             r.width() - 2 * d_data->borderWidth,
    00337             r.height() - 2 * d_data->borderWidth);
    00338
    00339         p->fillRect(cr.x(), cr.y(), cr.width(), cr.height(),
    00340 #if QT_VERSION < 0x040000
    00341             colorGroup().brush(QColorGroup::Mid)
    00342 #else
    00343             palette().brush(QPalette::Mid)
    00344 #endif
    00345         );
    00346     }
    00347
    00348     if ( d_data->bgStyle & BgSlot)
    00349     {
    00350         int ws = 4;
    00351         int ds = d_data->thumbLength / 2 - 4;
    00352         if ( ds < 1 )
    00353             ds = 1;
    00354
    00355         QRect rSlot;
    00356         if (orientation() == Qt::Horizontal)
    00357         {
    00358             if ( cr.height() & 1 )
    00359                 ws++;
    00360             rSlot = QRect(cr.x() + ds,
    00361                     cr.y() + (cr.height() - ws) / 2,
    00362                     cr.width() - 2 * ds, ws);
    00363         }
    00364         else
    00365         {
    00366             if ( cr.width() & 1 )
    00367                 ws++;
    00368             rSlot = QRect(cr.x() + (cr.width() - ws) / 2,
    00369                     cr.y() + ds,
    00370                     ws, cr.height() - 2 * ds);
    00371         }
    00372         p->fillRect(rSlot.x(), rSlot.y(), rSlot.width(), rSlot.height(),
    00373 #if QT_VERSION < 0x040000
    00374             colorGroup().brush(QColorGroup::Dark)
    00375 #else
    00376             palette().brush(QPalette::Dark)
    00377 #endif
    00378         );
    00379         qDrawShadePanel(p, rSlot.x(), rSlot.y(),
    00380             rSlot.width(), rSlot.height(),
    00381 #if QT_VERSION < 0x040000
    00382             colorGroup(),
    00383 #else
    00384             palette(),
    00385 #endif
    00386             true, 1 ,0);
    00387
    00388     }
    00389
    00390     if ( isValid() )
    00391         drawThumb(p, cr, xyPosition(value()));
    00392 }
    00393
    00395 void QwtSlider::drawThumb(QPainter *p, const QRect &sliderRect, int pos)
    00396 {
    00397     pos++; // shade line points one pixel below
    00398     if (orientation() == Qt::Horizontal)
    00399     {
    00400         qDrawShadePanel(p, pos - d_data->thumbLength / 2,
    00401             sliderRect.y(), d_data->thumbLength, sliderRect.height(),
    00402 #if QT_VERSION < 0x040000
    00403             colorGroup(),
    00404 #else
    00405             palette(),
    00406 #endif
    00407             false, d_data->borderWidth,
    00408 #if QT_VERSION < 0x040000
    00409             &colorGroup().brush(QColorGroup::Button)
    00410 #else
    00411             &palette().brush(QPalette::Button)
    00412 #endif
    00413         );
    00414
    00415         qDrawShadeLine(p, pos, sliderRect.y(),
    00416             pos, sliderRect.y() + sliderRect.height() - 2,
    00417 #if QT_VERSION < 0x040000
    00418             colorGroup(),
    00419 #else
    00420             palette(),
    00421 #endif
    00422             true, 1);
    00423     }
    00424     else // Vertical
    00425     {
    00426         qDrawShadePanel(p,sliderRect.x(), pos - d_data->thumbLength / 2,
    00427             sliderRect.width(), d_data->thumbLength,
    00428 #if QT_VERSION < 0x040000
    00429             colorGroup(),
    00430 #else
    00431             palette(),
    00432 #endif
    00433             false, d_data->borderWidth,
    00434 #if QT_VERSION < 0x040000
    00435             &colorGroup().brush(QColorGroup::Button)
    00436 #else
    00437             &palette().brush(QPalette::Button)
    00438 #endif
    00439         );
    00440
    00441         qDrawShadeLine(p, sliderRect.x(), pos,
    00442             sliderRect.x() + sliderRect.width() - 2, pos,
    00443 #if QT_VERSION < 0x040000
    00444             colorGroup(),
    00445 #else
    00446             palette(),
    00447 #endif
    00448             true, 1);
    00449     }
    00450 }
    00451
    00453 int QwtSlider::xyPosition(double v) const
    00454 {
    00455     return d_data->map.transform(v);
    00456 }
    00457
    00459 double QwtSlider::getValue(const QPoint &p)
    00460 {
    00461     return d_data->map.invTransform(
    00462         orientation() == Qt::Horizontal ? p.x() : p.y());
    00463 }
    00464
    00465
    00472 void QwtSlider::getScrollMode(const QPoint &p,
    00473     int &scrollMode, int &direction )
    00474 {
    00475     if (!d_data->sliderRect.contains(p))
    00476     {
    00477         scrollMode = ScrNone;
    00478         direction = 0;
    00479         return;
    00480     }
    00481
    00482     const int pos = ( orientation() == Qt::Horizontal ) ? p.x() : p.y();
    00483     const int markerPos = xyPosition(value());
    00484
    00485     if ((pos > markerPos - d_data->thumbLength / 2)
    00486         && (pos < markerPos + d_data->thumbLength / 2))
    00487     {
    00488         scrollMode = ScrMouse;
    00489         direction = 0;
    00490         return;
    00491     }
    00492
    00493     scrollMode = ScrPage;
    00494     direction = (pos > markerPos) ? 1 : -1;
    00495
    00496     if ( scaleDraw()->map().p1() > scaleDraw()->map().p2() )
    00497         direction = -direction;
    00498 }
    00499
    00501 void QwtSlider::paintEvent(QPaintEvent *e)
    00502 {
    00503     const QRect &ur = e->rect();
    00504     if ( ur.isValid() )
    00505     {
    00506 #if QT_VERSION < 0x040000
    00507         QwtPaintBuffer paintBuffer(this, ur);
    00508         draw(paintBuffer.painter(), ur);
    00509 #else
    00510         QPainter painter(this);
    00511         draw(&painter, ur);
    00512 #endif
    00513     }
    00514 }
    00515
    00517 void QwtSlider::draw(QPainter *painter, const QRect&)
    00518 {
    00519     if (d_data->scalePos != NoScale)
    00520     {
    00521 #if QT_VERSION < 0x040000
    00522         scaleDraw()->draw(painter, colorGroup());
    00523 #else
    00524         scaleDraw()->draw(painter, palette());
    00525 #endif
    00526     }
    00527
    00528     drawSlider(painter, d_data->sliderRect);
    00529
    00530     if ( hasFocus() )
    00531         QwtPainter::drawFocusRect(painter, this, d_data->sliderRect);
    00532 }
    00533
    00535 void QwtSlider::resizeEvent(QResizeEvent *)
    00536 {
    00537     layoutSlider( false );
    00538 }
    00539
    00546 void QwtSlider::layoutSlider( bool update_geometry )
    00547 {
    00548     int sliderWidth = d_data->thumbWidth;
    00549     int sld1 = d_data->thumbLength / 2 - 1;
    00550     int sld2 = d_data->thumbLength / 2 + d_data->thumbLength % 2;
    00551     if ( d_data->bgStyle & BgTrough )
    00552     {
    00553         sliderWidth += 2 * d_data->borderWidth;
    00554         sld1 += d_data->borderWidth;
    00555         sld2 += d_data->borderWidth;
    00556     }
    00557
    00558     int scd = 0;
    00559     if ( d_data->scalePos != NoScale )
    00560     {
    00561         int d1, d2;
    00562         scaleDraw()->getBorderDistHint(font(), d1, d2);
    00563         scd = qwtMax(d1, d2);
    00564     }
    00565
    00566     int slo = scd - sld1;
    00567     if ( slo < 0 )
    00568         slo = 0;
    00569
    00570     int x, y, length;
    00571
    00572     const QRect r = rect();
    00573     if (orientation() == Qt::Horizontal)
    00574     {
    00575         switch (d_data->scalePos)
    00576         {
    00577             case TopScale:
    00578             {
    00579                 d_data->sliderRect.setRect(
    00580                     r.x() + d_data->xMargin + slo,
    00581                     r.y() + r.height() -
    00582                     d_data->yMargin - sliderWidth,
    00583                     r.width() - 2 * d_data->xMargin - 2 * slo,
    00584                     sliderWidth);
    00585
    00586                 x = d_data->sliderRect.x() + sld1;
    00587                 y = d_data->sliderRect.y() - d_data->scaleDist;
    00588
    00589                 break;
    00590             }
    00591
    00592             case BottomScale:
    00593             {
    00594                 d_data->sliderRect.setRect(
    00595                     r.x() + d_data->xMargin + slo,
    00596                     r.y() + d_data->yMargin,
    00597                     r.width() - 2 * d_data->xMargin - 2 * slo,
    00598                     sliderWidth);
    00599
    00600                 x = d_data->sliderRect.x() + sld1;
    00601                 y = d_data->sliderRect.y() + d_data->sliderRect.height()
    00602                     + d_data->scaleDist;
    00603
    00604                 break;
    00605             }
    00606
    00607             case NoScale: // like Bottom, but no scale. See QwtSlider().
    00608             default:   // inconsistent orientation and scale position
    00609             {
    00610                 d_data->sliderRect.setRect(
    00611                     r.x() + d_data->xMargin + slo,
    00612                     r.y() + d_data->yMargin,
    00613                     r.width() - 2 * d_data->xMargin - 2 * slo,
    00614                     sliderWidth);
    00615
    00616                 x = d_data->sliderRect.x() + sld1;
    00617                 y = 0;
    00618
    00619                 break;
    00620             }
    00621         }
    00622         length = d_data->sliderRect.width() - (sld1 + sld2);
    00623     }
    00624     else // if (orientation() == Qt::Vertical
    00625     {
    00626         switch (d_data->scalePos)
    00627         {
    00628             case RightScale:
    00629                 d_data->sliderRect.setRect(
    00630                     r.x() + d_data->xMargin,
    00631                     r.y() + d_data->yMargin + slo,
    00632                     sliderWidth,
    00633                     r.height() - 2 * d_data->yMargin - 2 * slo);
    00634
    00635                 x = d_data->sliderRect.x() + d_data->sliderRect.width()
    00636                     + d_data->scaleDist;
    00637                 y = d_data->sliderRect.y() + sld1;
    00638
    00639                 break;
    00640
    00641             case LeftScale:
    00642                 d_data->sliderRect.setRect(
    00643                     r.x() + r.width() - sliderWidth - d_data->xMargin,
    00644                     r.y() + d_data->yMargin + slo,
    00645                     sliderWidth,
    00646                     r.height() - 2 * d_data->yMargin - 2 * slo);
    00647
    00648                 x = d_data->sliderRect.x() - d_data->scaleDist;
    00649                 y = d_data->sliderRect.y() + sld1;
    00650
    00651                 break;
    00652
    00653             case NoScale: // like Left, but no scale. See QwtSlider().
    00654             default:   // inconsistent orientation and scale position
    00655                 d_data->sliderRect.setRect(
    00656                     r.x() + r.width() - sliderWidth - d_data->xMargin,
    00657                     r.y() + d_data->yMargin + slo,
    00658                     sliderWidth,
    00659                     r.height() - 2 * d_data->yMargin - 2 * slo);
    00660
    00661                 x = 0;
    00662                 y = d_data->sliderRect.y() + sld1;
    00663
    00664                 break;
    00665         }
    00666         length = d_data->sliderRect.height() - (sld1 + sld2);
    00667     }
    00668
    00669     scaleDraw()->move(x, y);
    00670     scaleDraw()->setLength(length);
    00671
    00672     d_data->map.setPaintXInterval(scaleDraw()->map().p1(),
    00673         scaleDraw()->map().p2());
    00674
    00675     if ( update_geometry )
    00676     {
    00677         d_data->sizeHintCache = QSize(); // invalidate
    00678         updateGeometry();
    00679         update();
    00680     }
    00681 }
    00682
    00684 void QwtSlider::valueChange()
    00685 {
    00686     QwtAbstractSlider::valueChange();
    00687     update();
    00688 }
    00689
    00690
    00692 void QwtSlider::rangeChange()
    00693 {
    00694     d_data->map.setScaleInterval(minValue(), maxValue());
    00695
    00696     if (autoScale())
    00697         rescale(minValue(), maxValue());
    00698
    00699     QwtAbstractSlider::rangeChange();
    00700     layoutSlider();
    00701 }
    00702
    00708 void QwtSlider::setMargins(int xMargin, int yMargin)
    00709 {
    00710     if ( xMargin < 0 )
    00711         xMargin = 0;
    00712     if ( yMargin < 0 )
    00713         yMargin = 0;
    00714
    00715     if ( xMargin != d_data->xMargin || yMargin != d_data->yMargin )
    00716     {
    00717         d_data->xMargin = xMargin;
    00718         d_data->yMargin = yMargin;
    00719         layoutSlider();
    00720     }
    00721 }
    00722
    00726 void QwtSlider::setBgStyle(BGSTYLE st)
    00727 {
    00728     d_data->bgStyle = st;
    00729     layoutSlider();
    00730 }
    00731
    00735 QwtSlider::BGSTYLE QwtSlider::bgStyle() const
    00736 {
    00737     return d_data->bgStyle;
    00738 }
    00739
    00743 int QwtSlider::thumbLength() const
    00744 {
    00745     return d_data->thumbLength;
    00746 }
    00747
    00751 int QwtSlider::thumbWidth() const
    00752 {
    00753     return d_data->thumbWidth;
    00754 }
    00755
    00759 int QwtSlider::borderWidth() const
    00760 {
    00761     return d_data->borderWidth;
    00762 }
    00763
    00767 QSize QwtSlider::sizeHint() const
    00768 {
    00769     return minimumSizeHint();
    00770 }
    00771
    00777 QSize QwtSlider::minimumSizeHint() const
    00778 {
    00779     if (!d_data->sizeHintCache.isEmpty())
    00780         return d_data->sizeHintCache;
    00781
    00782     int sliderWidth = d_data->thumbWidth;
    00783     if (d_data->bgStyle & BgTrough)
    00784         sliderWidth += 2 * d_data->borderWidth;
    00785
    00786     int w = 0, h = 0;
    00787     if (d_data->scalePos != NoScale)
    00788     {
    00789         int d1, d2;
    00790         scaleDraw()->getBorderDistHint(font(), d1, d2);
    00791         int msMbd = qwtMax(d1, d2);
    00792
    00793         int mbd = d_data->thumbLength / 2;
    00794         if (d_data->bgStyle & BgTrough)
    00795             mbd += d_data->borderWidth;
    00796
    00797         if ( mbd < msMbd )
    00798             mbd = msMbd;
    00799
    00800         const int sdExtent = scaleDraw()->extent( QPen(), font() );
    00801         const int sdLength = scaleDraw()->minLength( QPen(), font() );
    00802
    00803         h = sliderWidth + sdExtent + d_data->scaleDist;
    00804         w = sdLength - 2 * msMbd + 2 * mbd;
    00805     }
    00806     else  // no scale
    00807     {
    00808         w = 200;
    00809         h = sliderWidth;
    00810     }
    00811
    00812     if ( orientation() == Qt::Vertical )
    00813         qSwap(w, h);
    00814
    00815     w += 2 * d_data->xMargin;
    00816     h += 2 * d_data->yMargin;
    00817
    00818     d_data->sizeHintCache = QSize(w, h);
    00819     return d_data->sizeHintCache;
    00820 }