00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004
00005 #include "CSScrollbar.h"
00006 #include "CSFont.h"
00007 #include "CSLAF.h"
00008
00009 const char *CSScrollbar::CLASS = "CSScrollbar";
00010
00011 CSScrollbar::CSScrollbar(int kind) : CSGrafikElement(0, 0)
00012 {
00013 static char *functionName="CSScrollbar";
00014 LOG_ENTER
00015 mKind = kind;
00016 mStart = 0;
00017 mEnd = 0;
00018 mDisplayStart = 0;
00019 mDisplayEnd = 0;
00020 mDisplayLength = 0;
00021 CSLayoutManagerXY *layoutManager = new CSLayoutManagerXY();
00022 layoutManager->setComponentSizeOnly(true);
00023 layoutManager->setPropagateSizeChangesOnly(true);
00024 setLayoutManager(layoutManager);
00025 if (mKind == TYPE_HORIZONTAL)
00026 {
00027 CSLayoutData layoutData = CSLayoutData(POSITION_SOUTH);
00028 layoutData.setStretchedHorizontal(true);
00029 setLayoutData(layoutData);
00030 }
00031 else if (mKind == TYPE_VERTICAL)
00032 {
00033 CSLayoutData layoutData = CSLayoutData(POSITION_EAST);
00034 layoutData.setStretchedVertical(true);
00035 setLayoutData(layoutData);
00036 }
00037
00038 mLess = 0;
00039 mMore = 0;
00040 mHandle = 0;
00041
00042 MESSAGE_SCROLLBAR_CHANGED.setSubtype(SCROLLBAR_POSITION_CHANGED_MESSAGE);
00043 rebuildElement();
00044 layoutSetup();
00045 LOG_EXIT
00046 }
00047
00048 void CSScrollbar::positionChanged()
00049 {
00050 static char *functionName="positionChanged";
00051 MESSAGE_SCROLLBAR_CHANGED.sender = this;
00052 MESSAGE_SCROLLBAR_CHANGED.start = mDisplayStart;
00053 MESSAGE_SCROLLBAR_CHANGED.end = mDisplayEnd;
00054 MESSAGE_SCROLLBAR_CHANGED.mIsHandled = false;
00055 sendMessage(MESSAGE_SCROLLBAR_CHANGED);
00056 }
00057
00058
00059
00060 void CSScrollbar::paint(SDL_Surface *destination, SDL_Rect *parentViewport)
00061 {
00062 static char *functionName="paint";
00063 CSGrafikElement *parent = getParent();
00064 if (!parent)
00065 {
00066 return;
00067 }
00068 int pw = mWidth;
00069 int ph = mHeight;
00070
00071 int overallLength = mEnd - mStart;
00072 int currentLength = mDisplayEnd - mDisplayStart;
00073 bool mustCallPositioning = false;
00074
00075 float handleLength = 1;
00076 if (!overallLength)
00077 {
00078 overallLength = mDisplayLength;
00079 }
00080 if (overallLength > mDisplayLength)
00081 {
00082 handleLength = (float) ((float) (currentLength) / (float) (overallLength));
00083 }
00084
00085 if (mKind == TYPE_HORIZONTAL)
00086 {
00087 mLess->setPosition(0, 0);
00088 mMore->setPosition(mWidth - mLess->getWidth(), 0);
00089 mHandle->setHeight(mHeight);
00090
00091 int w = (mWidth - 2*mLess->getWidth())*handleLength;
00092 if (w < 3) w = 3;
00093 if (w < 4) w = 4;
00094 if (mHandle->getWidth() != w)
00095 {
00096 mustCallPositioning = true;
00097 }
00098 mHandle->setWidth( w );
00099 if (mDisplayEnd == mEnd)
00100 {
00101 mHandle->setPosition(pw-mLess->getWidth()-mHandle->getWidth(), 0);
00102 }
00103 else
00104 {
00105 int handleSlideWay = mWidth - mLess->getWidth() - mMore->getWidth();
00106 float s = ((float)(handleSlideWay) / (float) overallLength);
00107 if (!s)
00108 {
00109 s=1;
00110 }
00111 mHandle->setPosition(mLess->getWidth() + ((float)((float)s) * ((float)mDisplayStart)), 0);
00112 }
00113 }
00114
00115 if (mKind == TYPE_VERTICAL)
00116 {
00117 mLess->setPosition(0, 0);
00118 mMore->setPosition(0, mHeight - mLess->getHeight());
00119
00120 mHandle->setWidth(mWidth);
00121 int h = (mHeight - 2*mLess->getHeight())*handleLength;
00122 if (h < 3) h = 3;
00123 if (h < 4) h = 4;
00124 if (mHandle->getHeight() != h)
00125 {
00126 mustCallPositioning = true;
00127 }
00128 mHandle->setHeight( h );
00129 if (mDisplayEnd == mEnd)
00130 {
00131 mHandle->setPosition(0, ph-mLess->getHeight()-mHandle->getHeight());
00132 }
00133 else
00134 {
00135 int handleSlideWay = mHeight - mLess->getHeight() - mMore->getHeight();
00136 float s = ((float)(handleSlideWay) / (float) overallLength);
00137 if (!s)
00138 {
00139 s=1;
00140 }
00141 mHandle->setPosition(0, mLess->getHeight() + ((float)((float)s) * ((float)mDisplayStart)));
00142 }
00143 }
00144
00145 paintChildren(destination, parentViewport);
00146
00147
00148 if (mustCallPositioning)
00149 {
00150 positionChanged();
00151 }
00152 }
00153
00154 void CSScrollbar::reactOnMessage(CSMessage *message)
00155 {
00156 reactOnMessageScrollbar(message);
00157 }
00158
00159 void CSScrollbar::reactOnMessageScrollbar(CSMessage *message)
00160 {
00161 static char *functionName="reactOnMessage";
00162 if (message->mIsHandled)
00163 {
00164 reactOnMessageGrafikElement(message);
00165 return;
00166 }
00167 if (message->getType() == GUI_MESSAGE)
00168 {
00169 GuiMessage *gm = (GuiMessage *) message;
00170 if (gm->receiver != this)
00171 {
00172 if (gm->getSubtype() == BUTTON_PRESSED_MESSAGE)
00173 {
00174 if (gm->actionId == SCROLL_BUTTON_LESS_ACTION_ID)
00175 {
00176 if (mDisplayStart > 0)
00177 {
00178 mDisplayStart--;
00179 mDisplayEnd = mDisplayStart+mDisplayLength;
00180 if (mDisplayEnd>mEnd)
00181 {
00182 mDisplayEnd = mEnd;
00183 }
00184 positionChanged();
00185 }
00186 }
00187
00188 if (gm->actionId == SCROLL_BUTTON_MORE_ACTION_ID)
00189 {
00190 if (mDisplayEnd < mEnd)
00191 {
00192 mDisplayEnd++;
00193 mDisplayStart=mDisplayEnd-mDisplayLength;
00194 if (mDisplayStart<0)
00195 {
00196 mDisplayStart = 0;
00197 }
00198 positionChanged();
00199 }
00200 }
00201 }
00202
00203 if (gm->getSubtype() == BUTTON_DRAGGED_MESSAGE)
00204 {
00205 int overallLength = mEnd - mStart;
00206 if (gm->actionId == SCROLL_BUTTON_DRAG_ACTION_ID)
00207 {
00208
00209 if (mKind == TYPE_VERTICAL)
00210 {
00211 int handleSlideWay = mHeight - mLess->getHeight() - mMore->getHeight();
00212 float s = ((float)(handleSlideWay) / (float) overallLength);
00213 if (!s)
00214 {
00215 s=1;
00216 }
00217 gm->deltaX = gm->screenX;
00218
00219 if (gm->deltaY >= s)
00220 {
00221 mDisplayEnd+=gm->deltaY/s;
00222 if (mDisplayEnd>mEnd)
00223 {
00224 mDisplayEnd = mEnd;
00225 }
00226 mDisplayStart = mDisplayEnd - mDisplayLength;
00227 if (mDisplayStart<0)
00228 {
00229 mDisplayStart = 0;
00230 }
00231 gm->deltaY = gm->screenY;
00232 positionChanged();
00233 }
00234 else if (-(gm->deltaY) >= s)
00235 {
00236 mDisplayStart+=gm->deltaY/s;
00237 if (mDisplayStart<0)
00238 {
00239 mDisplayStart = 0;
00240 }
00241
00242 mDisplayEnd = mDisplayStart + mDisplayLength;
00243 if (mDisplayEnd>mEnd)
00244 {
00245 mDisplayEnd = mEnd;
00246 }
00247 gm->deltaY = gm->screenY;
00248 positionChanged();
00249 }
00250 else
00251 {
00252 gm->deltaY = gm->screenY - gm->deltaY;
00253 }
00254 }
00255 else if (mKind == TYPE_HORIZONTAL)
00256 {
00257 int handleSlideWay = mWidth - mLess->getWidth() - mMore->getWidth();
00258 float s = ((float)(handleSlideWay) / (float) overallLength);
00259
00260 gm->deltaY = gm->screenY;
00261 if (gm->deltaX >= s)
00262 {
00263 mDisplayEnd+=gm->deltaX/s;
00264 if (mDisplayEnd>mEnd)
00265 {
00266 mDisplayEnd = mEnd;
00267 }
00268 mDisplayStart = mDisplayEnd - mDisplayLength;
00269 if (mDisplayStart<0)
00270 {
00271 mDisplayStart = 0;
00272 }
00273 gm->deltaX = gm->screenX;
00274 positionChanged();
00275 }
00276 else if (-(gm->deltaX) >= s)
00277 {
00278 mDisplayStart+=gm->deltaX/s;
00279 if (mDisplayStart<0)
00280 {
00281 mDisplayStart = 0;
00282 }
00283
00284 mDisplayEnd = mDisplayStart + mDisplayLength;
00285 if (mDisplayEnd>mEnd)
00286 {
00287 mDisplayEnd = mEnd;
00288 }
00289 gm->deltaX = gm->screenX;
00290 positionChanged();
00291 }
00292 else
00293 {
00294 gm->deltaX = gm->screenX - gm->deltaX;
00295 }
00296 }
00297 }
00298 }
00299 }
00300 else
00301 {
00302 switch (message->getSubtype())
00303 {
00304 case MOUSE_BUTTON_PRESSED_MESSAGE:
00305 {
00306 int x = gm->receiverX;
00307 int y = gm->receiverY;
00308
00309 if (mKind == TYPE_VERTICAL)
00310 {
00311 if (y <mHandle->getY())
00312 {
00313 mDisplayStart -= mDisplayLength;
00314 mDisplayEnd = mDisplayStart + mDisplayLength;
00315
00316 if (mDisplayStart<0)
00317 {
00318 mDisplayStart = 0;
00319 mDisplayEnd = mDisplayStart + mDisplayLength;
00320 }
00321 positionChanged();
00322 }
00323 else
00324 {
00325 mDisplayStart += mDisplayLength;
00326 mDisplayEnd = mDisplayStart + mDisplayLength;
00327
00328 if (mDisplayEnd>mEnd)
00329 {
00330 mDisplayEnd = mEnd;
00331 mDisplayStart = mEnd - mDisplayLength;
00332 }
00333 positionChanged();
00334 }
00335 }
00336 else if (mKind == TYPE_HORIZONTAL)
00337 {
00338 if (x <mHandle->getX())
00339 {
00340 mDisplayStart -= mDisplayLength;
00341 mDisplayEnd = mDisplayStart + mDisplayLength;
00342
00343 if (mDisplayStart<0)
00344 {
00345 mDisplayStart = 0;
00346 mDisplayEnd = mDisplayStart + mDisplayLength;
00347 }
00348 positionChanged();
00349 }
00350 else
00351 {
00352 mDisplayStart += mDisplayLength;
00353 mDisplayEnd = mDisplayStart + mDisplayLength;
00354
00355 if (mDisplayEnd>mEnd)
00356 {
00357 mDisplayEnd = mEnd;
00358 mDisplayStart = mEnd - mDisplayLength;
00359 }
00360 positionChanged();
00361 }
00362 }
00363 gm->mIsHandled = true;
00364 break;
00365 }
00366 }
00367 }
00368 }
00369 reactOnMessageGrafikElement(message);
00370 }
00371
00372 void CSScrollbar::rebuildElement()
00373 {
00374 static char *functionName="rebuildElement";
00375 LOG_ENTER
00376 CSLAF *laf = CSLAF::getCurrentLAF();
00377
00378 if (mMore != 0)
00379 {
00380 mMore->removeMessageListener(this);
00381 removeElement(mMore);
00382 delete (mMore);
00383 mMore = 0;
00384 }
00385
00386 if (mLess != 0)
00387 {
00388 mLess->removeMessageListener(this);
00389 removeElement(mLess);
00390 delete (mLess);
00391 mLess = 0;
00392 }
00393
00394 if (mHandle != 0)
00395 {
00396 mHandle->removeMessageListener(this);
00397 removeElement(mHandle);
00398 delete (mHandle);
00399 mHandle = 0;
00400 }
00401
00402 mHandle = new CSDragButton(0);
00403 if (mKind == TYPE_HORIZONTAL)
00404 {
00405 mLess = new CSButton(laf->getIcon(LAF_ICON_TYPE_LEFT));
00406 mMore = new CSButton(laf->getIcon(LAF_ICON_TYPE_RIGHT));
00407
00408 CSLayoutData layout = mHandle->getLayoutData();
00409 layout.setStretchedVertical(true);
00410 mHandle->setLayoutData(layout);
00411
00412 }
00413 if (mKind == TYPE_VERTICAL)
00414 {
00415 mLess = new CSButton(laf->getIcon(LAF_ICON_TYPE_UP));
00416 mMore = new CSButton(laf->getIcon(LAF_ICON_TYPE_DOWN));
00417
00418 CSLayoutData layout = mHandle->getLayoutData();
00419 layout.setStretchedHorizontal(true);
00420 mHandle->setLayoutData(layout);
00421
00422 }
00423 addElement(mLess, 0,0);
00424 addElement(mMore, 0,0);
00425 addElement(mHandle,0,0);
00426
00427 mMore->setFocusable(getFocusable());
00428 mLess->setFocusable(getFocusable());
00429 mHandle->setFocusable(getFocusable());
00430 mHandle->setInset(CSInset(0));
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 mLess->setActionId(SCROLL_BUTTON_LESS_ACTION_ID);
00441 mLess->addMessageListener(this, GUI_MESSAGE);
00442 mMore->setActionId(SCROLL_BUTTON_MORE_ACTION_ID);
00443 mMore->addMessageListener(this, GUI_MESSAGE);
00444 mHandle->setActionId(SCROLL_BUTTON_DRAG_ACTION_ID);
00445 mHandle->addMessageListener(this, GUI_MESSAGE);
00446
00447 LOG_EXIT
00448 }
00449
00450 void CSScrollbar::layoutSetupScrollbar()
00451 {
00452 static char *functionName="layoutSetupScrollbar";
00453 LOG_ENTER
00454 CSLAF *laf = CSLAF::getCurrentLAF();
00455 if (mKind == TYPE_HORIZONTAL)
00456 {
00457 mMinWidth = mLess->getWidth() + mMore->getWidth();
00458 mMinHeight = mLess->getHeight();
00459 }
00460 if (mKind == TYPE_VERTICAL)
00461 {
00462 mMinHeight = mLess->getHeight() + mMore->getHeight();
00463 mMinWidth = mLess->getWidth();
00464 }
00465
00466 LOG_EXIT
00467 }