00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004
00005 #include "CSDesktop.h"
00006 #include "CSWindow.h"
00007 #include "CSLabel.h"
00008 #include "CSFont.h"
00009 #include "CSArea.h"
00010 #include "CSBorder.h"
00011 #include "CSPanel.h"
00012
00013 #include <vector>
00014 #include <string>
00015
00016 #include "CSMouseCursor.h"
00017
00018
00019 const char *CSDesktop::CLASS = "CSDesktop";
00020
00021 CSDesktop::CSDesktop() : CSGrafikElement(0, 0)
00022 {
00023 static char *functionName="CSDesktop";
00024 LOG_ENTER
00025 mHeight = SDLMain::getScreenHeight();
00026 mWidth = SDLMain::getScreenWidth();
00027 mScreenArea.x = 0;
00028 mScreenArea.y = 0;
00029 mScreenArea.h = mHeight;
00030 mScreenArea.w = mWidth;
00031 mFocusedComponent = 0;
00032 mCurrentUnderMouseComponent = 0;
00033 mStartDown = 0;
00034 init(mHeight, mWidth);
00035
00036 mNorth = 0;
00037 mWest = 0;
00038 mSouth = 0;
00039 mEast = 0;
00040 mCenter = 0;
00041 setMainLayoutManager(new CSLayoutManagerBorder());
00042
00043 mNorth = new CSPanel();
00044 mNorth->setLayoutManager(new CSLayoutManagerStackVertical());
00045 mWest = new CSPanel();
00046 mWest->setLayoutManager(new CSLayoutManagerStackHorizontal());
00047 mSouth = new CSPanel();
00048 mSouth->setLayoutManager(new CSLayoutManagerStackVertical());
00049 mEast = new CSPanel();
00050 mEast->setLayoutManager(new CSLayoutManagerStackHorizontal());
00051 mCenter = new CSPanel();
00052
00053 CSLayoutData layout = CSLayoutData(POSITION_NORTH);
00054 layout.setStretchedHorizontal(true);
00055 layout.setPackedVertical(true);
00056 mNorth->setLayoutData(layout);
00057 addMainElement(mNorth);
00058
00059 layout.setPosition(POSITION_SOUTH);
00060 mSouth->setLayoutData(layout);
00061 addMainElement(mSouth);
00062
00063 layout.setPosition(POSITION_CENTER);
00064 layout.setStretchedVertical(true);
00065 mCenter->setLayoutData(layout);
00066 addMainElement(mCenter);
00067 setMainElement(mCenter);
00068
00069 layout.setPackedHorizontal(true);
00070 layout.setPosition(POSITION_WEST);
00071 mWest->setLayoutData(layout);
00072 addMainElement(mWest);
00073
00074 layout.setPosition(POSITION_EAST);
00075 mEast->setLayoutData(layout);
00076 addMainElement(mEast);
00077
00078 mLastTimePainted = -1;
00079 mLastCursorX = -1;
00080 mLastCursorY = -1;
00081 mModalComponent = 0;
00082 mTooltipPanel = new CSPanel(0, 0);
00083 mTooltipPanel->setLayoutManager(new CSLayoutManagerStackVertical());
00084 layout = CSLayoutData(0,0);
00085 layout.setPackedVertical(true);
00086 layout.setPackedHorizontal(true);
00087 mTooltipPanel->setLayoutData(layout);
00088 mTooltipLabel = new CSLabel("");
00089 mTooltipLabel->setLayoutData(CSLayoutData(POSITION_ORDER_TOP));
00090 mTooltipPanel->addElement(mTooltipLabel);
00091 addMainElement(mTooltipPanel);
00092 LOG_EXIT
00093 }
00094
00095 CSDesktop::CSDesktop(SDL_Rect area) : CSGrafikElement(area.h, area.w)
00096 {
00097 static char *functionName="CSDesktop";
00098 LOG_ENTER
00099 mX = area.x;
00100 mY = area.y;
00101 mViewportX = area.x;
00102 mViewportY = area.y;
00103
00104 mFocusedComponent = 0;
00105 mCurrentUnderMouseComponent = 0;
00106 mStartDown = 0;
00107 LOG_EXIT
00108 }
00109
00110 CSDesktop::~CSDesktop()
00111 {
00112 static char *functionName="~CSDesktop";
00113 LOG_ENTER
00114 LOG_EXIT
00115 }
00116
00117 void CSDesktop::showToolTip()
00118 {
00119 int receiverX, receiverY;
00120 CSGrafikElement *element = getElement(mCursorX, mCursorY, &mScreenArea, receiverX, receiverY);
00121 std::string text = element->getTooltipText();
00122 if (text.length() > 0)
00123 {
00124 if (!mTooltipPanel->getVisible())
00125 {
00126 mTooltipLabel->setText(text);
00127 mTooltipPanel->setPosition(mCursorX, mCursorY);
00128 toFront(mTooltipPanel);
00129 mTooltipPanel->setVisible(true);
00130 }
00131 }
00132 }
00133
00134 void CSDesktop::paint(SDL_Surface *destination, SDL_Rect *parentViewport)
00135 {
00136 static char *functionName="paint";
00137 CSLAF *laf = CSLAF::getCurrentLAF();
00138 long mCurrentTime = SDL_GetTicks();
00139 doLayout();
00140
00141 if (getFont())
00142 {
00143 getFont()->setSolid(true);
00144 std::string type="";
00145 if (mFocusedComponent)
00146 {
00147 type = mFocusedComponent->getType().c_str();
00148 }
00149 char str[100];
00150 sprintf(str, "%s ",type.c_str());
00151 getFont()->putString(SDLMain::getScreen(), 0, 320, str);
00152 }
00153
00154
00155 if ((mLastCursorX == mCursorX) && (mLastCursorY == mCursorY))
00156 {
00157 long t = mCurrentTime - mLastTimePainted;
00158 if (t >= laf->tooltipThreshold)
00159 {
00160 showToolTip();
00161 }
00162 }
00163 else
00164 {
00165 mTooltipPanel->setVisible(false);
00166 mLastTimePainted = mCurrentTime;
00167 }
00168 mLastCursorX = mCursorX;
00169 mLastCursorY = mCursorY;
00170
00171 SDL_Rect thisArea = mElementArea;
00172 if (parentViewport)
00173 {
00174 thisArea.x += parentViewport->x;
00175 thisArea.y += parentViewport->y;
00176 }
00177
00178 SDL_Rect thisAreaCopy = thisArea;
00179
00180 SDL_SetClipRect(destination, &thisAreaCopy);
00181 if (parentViewport)
00182 {
00183 paintChildren(destination, parentViewport);
00184 }
00185 else
00186 {
00187 paintChildren(destination, &mScreenArea);
00188 }
00189
00190 int receiverX, receiverY;
00191 CSGrafikElement *receiver = getElement(mCursorX, mCursorY, &mScreenArea, receiverX, receiverY);
00192 if (receiver)
00193 {
00194 receiver->getCursor()->setPosition(mCursorX, mCursorY);
00195 receiver->getCursor()->paint(destination, &thisArea);
00196 }
00197 else
00198 {
00199 getCursor()->setPosition(mCursorX, mCursorY);
00200 getCursor()->paint(destination, &thisArea);
00201 }
00202 SDL_SetClipRect(destination, 0);
00203 }
00204
00205 void CSDesktop::addElementNorth(CSGrafikElement *element)
00206 {
00207 mNorth->addElement(element);
00208 }
00209
00210 void CSDesktop::addElementSouth(CSGrafikElement *element)
00211 {
00212 mSouth->addElement(element);
00213 }
00214
00215 void CSDesktop::addElementEast(CSGrafikElement *element)
00216 {
00217 mEast->addElement(element);
00218 }
00219
00220 void CSDesktop::addElementWest(CSGrafikElement *element)
00221 {
00222 mWest->addElement(element);
00223 }
00224
00225 void CSDesktop::onMouseMotion(int x, int y)
00226 {
00227 static char *functionName="onMouseMotion";
00228 mCursorX = x;
00229 mCursorY = y;
00230 MESSAGE_MOUSE_MOTION.receiver = getElement(x, y, &mScreenArea, MESSAGE_MOUSE_MOTION.receiverX, MESSAGE_MOUSE_MOTION.receiverY);
00231 if ((mModalComponent) && (!mModalComponent->isChild(MESSAGE_MOUSE_MOTION.receiver)))
00232 {
00233 if ((mCurrentUnderMouseComponent!=0) && (mCurrentUnderMouseComponent != MESSAGE_MOUSE_MOTION.receiver))
00234 {
00235 if (mStartDown == mCurrentUnderMouseComponent)
00236 {
00237 MESSAGE_MOUSE_MOTION.screenX = x;
00238 MESSAGE_MOUSE_MOTION.screenY = y;
00239 MESSAGE_MOUSE_MOTION.sender = this;
00240 MESSAGE_MOUSE_MOTION.mIsHandled = false;
00241 MESSAGE_MOUSE_MOTION.receiver = mStartDown;
00242 mStartDown->sendMessage(MESSAGE_MOUSE_MOTION);
00243 return;
00244 }
00245 }
00246 return;
00247 }
00248 if ((mCurrentUnderMouseComponent!=0) && (mCurrentUnderMouseComponent != MESSAGE_MOUSE_MOTION.receiver))
00249 {
00250 if (mStartDown == mCurrentUnderMouseComponent)
00251 {
00252 MESSAGE_MOUSE_MOTION.screenX = x;
00253 MESSAGE_MOUSE_MOTION.screenY = y;
00254 MESSAGE_MOUSE_MOTION.sender = this;
00255 MESSAGE_MOUSE_MOTION.mIsHandled = false;
00256 MESSAGE_MOUSE_MOTION.receiver = mStartDown;
00257 mStartDown->sendMessage(MESSAGE_MOUSE_MOTION);
00258 return;
00259 }
00260 else
00261 {
00262
00263 MESSAGE_MOUSE_MOTION_LOST.screenX = x;
00264 MESSAGE_MOUSE_MOTION_LOST.screenY = y;
00265 MESSAGE_MOUSE_MOTION_LOST.sender = this;
00266 MESSAGE_MOUSE_MOTION_LOST.mIsHandled = false;
00267 MESSAGE_MOUSE_MOTION_LOST.receiver = mCurrentUnderMouseComponent;
00268 mCurrentUnderMouseComponent->sendMessage(MESSAGE_MOUSE_MOTION_LOST);
00269 }
00270 }
00271 MESSAGE_MOUSE_MOTION.screenX = x;
00272 MESSAGE_MOUSE_MOTION.screenY = y;
00273 MESSAGE_MOUSE_MOTION.sender = this;
00274 MESSAGE_MOUSE_MOTION.mIsHandled = false;
00275 MESSAGE_MOUSE_MOTION.receiver = getElement(x, y, &mScreenArea, MESSAGE_MOUSE_MOTION.receiverX, MESSAGE_MOUSE_MOTION.receiverY);
00276 mCurrentUnderMouseComponent = MESSAGE_MOUSE_MOTION.receiver;
00277 if (mStartDown)
00278 {
00279 mStartDown->sendMessage(MESSAGE_MOUSE_MOTION);
00280 }
00281 else
00282 {
00283 if (MESSAGE_MOUSE_MOTION.receiver)
00284 {
00285 MESSAGE_MOUSE_MOTION.receiver->sendMessage(MESSAGE_MOUSE_MOTION);
00286 }
00287 }
00288 }
00289
00290 void CSDesktop::onMouseDown(int x, int y)
00291 {
00292 static char *functionName="onMouseDown";
00293 bool focusedComponentMessaged = false;
00294
00295 LOG_ENTER
00296 MESSAGE_MOUSE_PRESSED.screenX = x;
00297 MESSAGE_MOUSE_PRESSED.screenY = y;
00298 MESSAGE_MOUSE_PRESSED.sender = this;
00299 MESSAGE_MOUSE_PRESSED.mIsHandled = false;
00300 MESSAGE_MOUSE_PRESSED.receiver = getElement(x, y, &mScreenArea, MESSAGE_MOUSE_PRESSED.receiverX, MESSAGE_MOUSE_PRESSED.receiverY);
00301 if ((mModalComponent) && (!mModalComponent->isChild(MESSAGE_MOUSE_PRESSED.receiver)))
00302 {
00303 return;
00304 }
00305 if (MESSAGE_MOUSE_PRESSED.receiver)
00306 {
00307
00308
00309
00310
00311
00312
00313 if (MESSAGE_MOUSE_PRESSED.receiver->getFocusable())
00314 {
00315 setFocusedComponent(0);
00316 focusedComponentMessaged = true;
00317 }
00318 int receiverX, receiverY;
00319 CSGrafikElement *receiver = getElement(x, y, &mScreenArea, receiverX, receiverY);
00320 MESSAGE_MOUSE_PRESSED.receiver->sendMessage(MESSAGE_MOUSE_PRESSED);
00321 if (receiver == MESSAGE_MOUSE_PRESSED.receiver)
00322 {
00323 if (receiver->getFocusable())
00324 {
00325 setFocusedComponent(receiver);
00326 focusedComponentMessaged = true;
00327 }
00328 mStartDown = receiver;
00329 }
00330 else
00331 {
00332 mStartDown = 0;
00333 setFocusedComponent(0);
00334 focusedComponentMessaged = true;
00335 }
00336 }
00337 else
00338 {
00339 setFocusedComponent(0);
00340 focusedComponentMessaged = true;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 LOG_EXIT
00356 }
00357
00358 void CSDesktop::onMouseUp(int x, int y)
00359 {
00360 static char *functionName="onMouseUp";
00361 LOG_ENTER
00362 MESSAGE_MOUSE_RELEASED.screenX = x;
00363 MESSAGE_MOUSE_RELEASED.screenY = y;
00364 MESSAGE_MOUSE_RELEASED.sender = this;
00365 MESSAGE_MOUSE_RELEASED.mIsHandled = false;
00366 MESSAGE_MOUSE_RELEASED.receiver = getElement(x, y, &mScreenArea, MESSAGE_MOUSE_RELEASED.receiverX, MESSAGE_MOUSE_RELEASED.receiverY);
00367 MESSAGE_MOUSE_RELEASED.downReceiver = mStartDown;
00368 if ((mModalComponent) && (!mModalComponent->isChild(MESSAGE_MOUSE_RELEASED.receiver)))
00369 {
00370 return;
00371 }
00372
00373 if ((MESSAGE_MOUSE_RELEASED.receiver) && (MESSAGE_MOUSE_RELEASED.receiver == mStartDown))
00374 {
00375 MESSAGE_MOUSE_RELEASED.receiver->sendMessage(MESSAGE_MOUSE_RELEASED);
00376 }
00377 if (mStartDown != MESSAGE_MOUSE_RELEASED.receiver)
00378 {
00379 if (mStartDown)
00380 {
00381 mStartDown->sendMessage(MESSAGE_MOUSE_RELEASED);
00382 }
00383 }
00384 mStartDown = 0;
00385 LOG_EXIT
00386 }
00387
00388 void CSDesktop::setFocusedComponent(CSGrafikElement *element)
00389 {
00390 static char *functionName="setFocusedComponent";
00391 LOG_ENTER
00392 if (mFocusedComponent == element)
00393 {
00394 return;
00395 }
00396 if (mFocusedComponent)
00397 {
00398 MESSAGE_FOCUS_LOST.screenX = 0;
00399 MESSAGE_FOCUS_LOST.screenY = 0;
00400 MESSAGE_FOCUS_LOST.sender = this;
00401 MESSAGE_FOCUS_LOST.mIsHandled = false;
00402 MESSAGE_FOCUS_LOST.receiver = mFocusedComponent;
00403 mFocusedComponent->setFocused(false);
00404
00405 CSGrafikElement *component = mFocusedComponent;
00406 while ((!MESSAGE_FOCUS_LOST.mIsHandled) && (component != 0))
00407 {
00408 component->sendMessage(MESSAGE_FOCUS_LOST);
00409 component = component->getParent();
00410 }
00411 }
00412
00413 if (element)
00414 {
00415 if (element->getFocusable())
00416 {
00417 MESSAGE_FOCUS_GAINED.screenX = 0;
00418 MESSAGE_FOCUS_GAINED.screenY = 0;
00419 MESSAGE_FOCUS_GAINED.sender = this;
00420 MESSAGE_FOCUS_GAINED.mIsHandled = false;
00421 MESSAGE_FOCUS_GAINED.receiver = element;
00422 mFocusedComponent = element;
00423 mFocusedComponent->setFocused(true);
00424 mFocusedComponent->sendMessage(MESSAGE_FOCUS_GAINED);
00425 }
00426 else
00427 {
00428 mFocusedComponent = 0;
00429 }
00430 }
00431 else
00432 {
00433 mFocusedComponent = element;
00434 }
00435 LOG_EXIT
00436 }
00437
00438 void CSDesktop::focusedNextComponent()
00439 {
00440 static char *functionName="focusedNextComponent";
00441 LOG_ENTER
00442 if (mFocusedComponent == 0)
00443 {
00444 LOG_EXIT
00445 return;
00446 }
00447 CSGrafikElement *component = 0;
00448
00449 setFocusedComponent(component);
00450 LOG_EXIT
00451 }
00452
00453 bool CSDesktop::dispatchKeyEvent(const SDL_Event &event, int state)
00454 {
00455 static char *functionName="dispatchKeyEvent";
00456 LOG_ENTER
00457 GuiMessage *message = &MESSAGE_KEY_PRESSED;
00458 if (state == SDL_KEYUP)
00459 {
00460 message = &MESSAGE_KEY_RELEASED;
00461 }
00462
00463 message->screenX = 0;
00464 message->screenY = 0;
00465 message->sender = this;
00466 message->mIsHandled = false;
00467 message->keyUnicodeChar = event.key.keysym.unicode;
00468 message->keySymbolic = event.key.keysym.sym;
00469
00470 if (mFocusedComponent)
00471 {
00472 message->receiver = mFocusedComponent;
00473 }
00474 else
00475 {
00476 message->receiver = this;
00477 }
00478 message->receiver->sendMessage(*message);
00479
00480 LOG_EXIT
00481 return message->mIsHandled;
00482 }
00483
00484 void CSDesktop::runModalDesktop(CSGrafikElement *modalElement, SDL_Surface *destination)
00485 {
00486 static char *functionName = "runModalDesktop";
00487 LOG_ENTER
00488 SDL_Surface *mBack = 0;
00489 SDL_SetClipRect(destination, 0);
00490 mModalComponent = modalElement;
00491 int flags = destination->flags;
00492 if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE)
00493 {
00494 flags -= SDL_HWSURFACE;
00495 }
00496 if ((flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF)
00497 {
00498 flags -= SDL_DOUBLEBUF;
00499 }
00500 if ((flags & SDL_FULLSCREEN) == SDL_FULLSCREEN)
00501 {
00502 flags -= SDL_FULLSCREEN;
00503 }
00504
00505 mBack = SDL_CreateRGBSurface(
00506 flags,
00507 destination->w,
00508 destination->h,
00509 destination->format->BitsPerPixel,
00510 destination->format->Rmask,
00511 destination->format->Gmask,
00512 destination->format->Bmask,
00513 destination->format->Amask);
00514 if (mBack == 0)
00515 {
00516 LOG_EXIT
00517 SDLMain::shutdown((std::string)"Display Format error: " + SDL_GetError(), 1);
00518 }
00519 if (SDL_BlitSurface(destination, 0, mBack, 0) < 0)
00520 {
00521 LOG_EXIT
00522 SDLMain::shutdown((std::string)"BlitSurface error: " + SDL_GetError(), 1);
00523 }
00524 do
00525 {
00526 handleEvents();
00527 doLayout();
00528
00529 if (SDL_BlitSurface(mBack, 0, destination, 0) < 0)
00530 {
00531 SDLMain::shutdown((std::string)"BlitSurface error: " + SDL_GetError(), 1);
00532 }
00533 SDL_Rect viewportAreaCopy = mViewportArea;
00534 SDL_Rect areaCopy = mElementArea;
00535 modalElement->paintArea(destination, &viewportAreaCopy);
00536 modalElement->paint(destination, &viewportAreaCopy);
00537 modalElement->paintBorder(destination, &viewportAreaCopy);
00538
00539 int receiverX, receiverY;
00540 CSGrafikElement *receiver = getElement(mCursorX, mCursorY, &mScreenArea, receiverX, receiverY);
00541 if (receiver)
00542 {
00543 receiver->getCursor()->setPosition(mCursorX, mCursorY);
00544 receiver->getCursor()->paint(destination, &areaCopy);
00545 }
00546 else
00547 {
00548 getCursor()->setPosition(mCursorX, mCursorY);
00549 getCursor()->paint(destination, &areaCopy);
00550 }
00551
00552 SDLMain::updateScreen();
00553 } while(modalElement->getVisible());
00554
00555 if (mBack)
00556 {
00557 SDL_FreeSurface(mBack);
00558 mBack = 0;
00559 }
00560 mModalComponent = 0;
00561 LOG_EXIT
00562 }
00563
00564 void CSDesktop::onMouseMotion(SDL_MouseMotionEvent event)
00565 {
00566 static char *functionName="onMouseMotion";
00567 if (isIn(event.x,event.y, &mElementArea))
00568 {
00569 onMouseMotion(event.x,event.y);
00570 }
00571 }
00572
00573 void CSDesktop::onMouseButtonDown(SDL_MouseButtonEvent event)
00574 {
00575 static char *functionName="onMouseButtonDown";
00576 LOG_ENTER
00577 if (isIn(event.x,event.y, &mElementArea))
00578 {
00579 onMouseDown(event.x,event.y);
00580 }
00581 LOG_EXIT
00582 }
00583
00584 void CSDesktop::onMouseButtonUp(SDL_MouseButtonEvent event)
00585 {
00586 static char *functionName="onMouseButtonUp";
00587 LOG_ENTER
00588 if (isIn(event.x,event.y, &mElementArea))
00589 {
00590 onMouseUp(event.x,event.y);
00591 }
00592 LOG_EXIT
00593 }
00594
00595 void CSDesktop::handleEvents()
00596 {
00597 static char *functionName="handleEvents";
00598 SDL_Event event;
00599
00600 if (SDL_PeepEvents(&event, 1, SDL_PEEKEVENT,SDL_MOUSEMOTIONMASK)==1)
00601 {
00602 do
00603 {
00604 SDL_PeepEvents(&event,1, SDL_GETEVENT,SDL_MOUSEMOTIONMASK);
00605 } while (SDL_PeepEvents(&event,1 , SDL_PEEKEVENT,SDL_MOUSEMOTIONMASK)==1);
00606
00607 onMouseMotion(event.motion);
00608 }
00609
00610 if (SDL_PollEvent(&event))
00611 {
00612 switch(event.type)
00613 {
00614 case SDL_MOUSEMOTION:
00615 {
00616 onMouseMotion(event.motion);
00617 break;
00618 }
00619 case SDL_MOUSEBUTTONDOWN:
00620 {
00621 onMouseButtonDown(event.button);
00622 break;
00623 }
00624 case SDL_MOUSEBUTTONUP:
00625 {
00626 onMouseButtonUp(event.button);
00627 break;
00628 }
00629 case SDL_KEYDOWN:
00630 {
00631 dispatchKeyEvent(event, SDL_KEYDOWN);
00632 }
00633 case SDL_KEYUP:
00634 {
00635 dispatchKeyEvent(event, SDL_KEYUP);
00636 }
00637 break;
00638 }
00639 }
00640 }
00641
00642 void CSDesktop::layoutSetupDesktop()
00643 {
00644 static char *functionName="layoutSetupDesktop";
00645 LOG_ENTER
00646 LOG_EXIT
00647 }
00648
00649 void CSDesktop::correctElementHandling(CSGrafikElement *element)
00650 {
00651 if (mFocusedComponent == element)
00652 {
00653 mFocusedComponent = 0;
00654 }
00655 if (mStartDown == element)
00656 {
00657 mStartDown = 0;
00658 }
00659 if (mCurrentUnderMouseComponent == element)
00660 {
00661 mCurrentUnderMouseComponent = 0;
00662 }
00663 if (mModalComponent == element)
00664 {
00665 mModalComponent = 0;
00666 }
00667 }