00001 #ifdef WIN32
00002 #pragma warning(disable : 4786 )
00003 #endif
00004
00005 #include "CSCombobox.h"
00006 #include "CSFont.h"
00007 #include "CSDesktop.h"
00008 #include "CSLAF.h"
00009 #include "CSButton.h"
00010 #include "CSListbox.h"
00011 const char *CSCombobox::CLASS = "CSCombobox";
00012
00013 CSCombobox::CSCombobox(int width) : CSGrafikElement(0, width)
00014 {
00015 static char *functionName="CSCombobox";
00016 LOG_ENTER
00017 init("");
00018 LOG_EXIT
00019 }
00020
00021 CSCombobox::~CSCombobox()
00022 {
00023 }
00024
00025 void CSCombobox::init(const std::string &text)
00026 {
00027 static char *functionName="init";
00028 LOG_ENTER
00029 mString = text;
00030 CSLAF *laf = CSLAF::getCurrentLAF();
00031
00032 mTickTimeNext = 0;
00033 mCursorRate = laf->getCursorRate();
00034 mCursorShown = false;
00035
00036 mListboxActive = false;
00037 mIsEditable = true;
00038 setEnabled(false);
00039 mListbox = 0;
00040 mMore = 0;
00041 mTextfield = 0;
00042 mListbox = 0;
00043 MESSAGE_COMBOBOX_ITEM_SELECTED.setSubtype(COMBOBOX_ITEM_SELECTED_MESSAGE);
00044 setLayoutManager(new CSLayoutManagerBorder());
00045 CSLayoutData layoutData = getLayoutData();
00046 layoutData.setPackedVertical(true);
00047 setLayoutData(layoutData);
00048
00049 rebuildElement();
00050 layoutSetup();
00051 LOG_EXIT
00052 }
00053
00054 void CSCombobox::putString(SDL_Surface *destination, SDL_Rect *parentViewport, int x1, int y1, const std::string &string)
00055 {
00056 static char *functionName="putString";
00057 x1 += parentViewport->x + getX();
00058 y1 += parentViewport->y + getY();
00059 getFont()->putString(destination, x1, y1, getTextColor(), string);
00060 }
00061
00062
00063
00064 void CSCombobox::paint(SDL_Surface *destination, SDL_Rect *parentViewport)
00065 {
00066 static char *functionName="paint";
00067 SDL_Rect rectSave;
00068 SDL_GetClipRect(destination, &rectSave);
00069
00070 SDL_Rect rectClip = getViewportArea();
00071 rectClip.x += parentViewport->x + getX();
00072 rectClip.y += parentViewport->y + getY();
00073
00074 SDLMain::adjustClipping(rectClip, rectSave);
00075 SDL_SetClipRect(destination, &rectClip);
00076
00077 int xOffset = getBorder()->getSizeWest() + getInset().getSizeWest() + mComboBoxInset.getSizeWest();
00078 int yOffset = getBorder()->getSizeNorth() + getInset().getSizeNorth() + mComboBoxInset.getSizeNorth();
00079
00080 if ((getFocused()) && (getEnabled()))
00081 {
00082 float currentTick = SDL_GetTicks() + mCursorRate;
00083 if (currentTick > mTickTimeNext)
00084 {
00085 mTickTimeNext = currentTick + mCursorRate;
00086 mCursorShown = !mCursorShown;
00087 }
00088 putString(destination, parentViewport, xOffset, yOffset + mTextOffset, mWorkingString);
00089 if (mCursorShown)
00090 {
00091 int witdh = getFont()->getWidth(mWorkingString);
00092 putString(destination, parentViewport, xOffset + witdh, yOffset + mTextOffset, "_");
00093 }
00094 }
00095 else
00096 {
00097 putString(destination, parentViewport, xOffset, yOffset + mTextOffset, mString);
00098 }
00099 SDL_SetClipRect(destination, &rectSave);
00100 paintChildren(destination, parentViewport);
00101 }
00102
00103 CSStringlist CSCombobox::getItems()
00104 {
00105 if (!mListbox)
00106 {
00107 return CSStringlist();
00108 }
00109 return mListbox->getItems();
00110 }
00111
00112 void CSCombobox::setItems(const CSStringlist &list)
00113 {
00114 if (mListbox)
00115 {
00116 mListbox->setItems(list);
00117 }
00118 }
00119
00120 std::string CSCombobox::getSelectedString()
00121 {
00122 if (!mListbox)
00123 {
00124 return std::string();
00125 }
00126
00127 return mListbox->getItems().getString(mListbox->getSelected());
00128 }
00129
00130
00131 void *CSCombobox::getSelectedObject()
00132 {
00133 if (!mListbox)
00134 {
00135 return 0;
00136 }
00137
00138 return mListbox->getItems().getObject(mListbox->getSelected());
00139 }
00140
00141 void CSCombobox::setSelected(int i)
00142 {
00143 if (!mListbox)
00144 {
00145 return ;
00146 }
00147 mListbox->setSelected(i);
00148 }
00149
00150 void CSCombobox::reactOnMessage(CSMessage *message)
00151 {
00152 reactOnMessageCombobox(message);
00153 }
00154
00155 void CSCombobox::reactOnMessageCombobox(CSMessage *message)
00156 {
00157 static char *functionName="reactOnMessage";
00158 if (message->mIsHandled)
00159 {
00160 reactOnMessageGrafikElement(message);
00161 return;
00162 }
00163
00164 if (message->getType() == GUI_MESSAGE)
00165 {
00166 GuiMessage *gm = (GuiMessage *) message;
00167 if (gm->receiver != this)
00168 {
00169 if (gm->getSubtype() == BUTTON_PRESSED_MESSAGE)
00170 {
00171 if (gm->actionId == COMBOBOX_BUTTON_MORE_ACTION_ID)
00172 {
00173 setListActive(!mListboxActive);
00174 }
00175 else
00176 {
00177 setListActive(false);
00178 }
00179 gm->mIsHandled = true;
00180 }
00181
00182 if (gm->getSubtype() == LIST_ITEM_SELECTED_MESSAGE)
00183 {
00184 setListActive(true);
00185 setListActive(false);
00186 getDesktop()->setFocusedComponent(0);
00187 mString = getSelectedString();
00188
00189 MESSAGE_COMBOBOX_ITEM_SELECTED.selected = gm->selected;
00190 MESSAGE_COMBOBOX_ITEM_SELECTED.actionId = mActionId;
00191 MESSAGE_COMBOBOX_ITEM_SELECTED.mIsHandled = false;
00192 sendMessage(MESSAGE_COMBOBOX_ITEM_SELECTED);
00193 gm->mIsHandled = true;
00194 }
00195 if (gm->getSubtype() == FOCUS_LOST_MESSAGE)
00196 {
00197 if (getEnabled())
00198 {
00199 mString = mWorkingString;
00200 setEnabled(false);
00201 }
00202 setListActive(false);
00203 gm->mIsHandled = true;
00204 }
00205 }
00206 else
00207 {
00208 switch (message->getSubtype())
00209 {
00210 case FOCUS_GAINED_MESSAGE:
00211 {
00212 if (mIsEditable)
00213 {
00214 mWorkingString = mString;
00215 setEnabled(true);
00216 setListActive(!mListboxActive);
00217 }
00218 gm->mIsHandled = true;
00219 break;
00220 }
00221
00222 case FOCUS_LOST_MESSAGE:
00223 {
00224 if (getEnabled())
00225 {
00226 mString = mWorkingString;
00227 setEnabled(false);
00228 }
00229 setListActive(false);
00230 gm->mIsHandled = true;
00231 break;
00232 }
00233
00234 case MOUSE_BUTTON_PRESSED_MESSAGE:
00235 {
00236 setListActive(true);
00237 gm->mIsHandled = true;
00238 break;
00239 }
00240
00241 case KEY_PRESSED_MESSAGE:
00242 {
00243 if (!getEnabled())
00244 {
00245 break;
00246 }
00247 int ch=gm->keyUnicodeChar;
00248
00249 if ((gm->keySymbolic == SDLK_RETURN) ||
00250 (gm->keySymbolic == SDLK_KP_ENTER) ||
00251 (gm->keySymbolic == SDLK_TAB))
00252 {
00253 getDesktop()->focusedNextComponent();
00254 gm->mIsHandled = true;
00255 break;
00256 }
00257 if (((ch>31)||(ch=='\b')) && (ch<128))
00258 {
00259 int len = mWorkingString.length();
00260 if (ch=='\b')
00261 {
00262 if (len>0)
00263 {
00264 mWorkingString.resize(len-1);
00265 }
00266 }
00267 else
00268 {
00269 mWorkingString += (char) ch;
00270
00271 len = mWorkingString.length();
00272 int witdh = getFont()->getWidth(mWorkingString) + getFont()->getWidth("_");
00273 if (witdh > getWidth() - (getBorder()->getSizeWest()))
00274 {
00275 mWorkingString.resize(len-1);
00276 }
00277 }
00278 gm->mIsHandled = true;
00279 }
00280 break;
00281 }
00282 }
00283 }
00284 }
00285 reactOnMessageGrafikElement(message);
00286 }
00287
00288 void CSCombobox::setListActive(bool active)
00289 {
00290 if (active == mListboxActive)
00291 {
00292 return;
00293 }
00294 mListboxActive = active;
00295
00296 if (!mListboxActive)
00297 {
00298 mListboxActive = false;
00299 mListbox->setVisible(false);
00300 CSDesktop *desktop = getDesktop();
00301 desktop->removeFrontElement(mListbox);
00302 }
00303 else
00304 {
00305 mListboxActive = true;
00306 mListbox->setVisible(true);
00307
00308 int x = 0;
00309 int y = getHeight();
00310 translateToDesktop(x, y);
00311 CSDesktop *desktop = getDesktop();
00312 desktop->addFrontElement(mListbox, x, y);
00313 }
00314 }
00315
00316 void CSCombobox::rebuildElement()
00317 {
00318 static char *functionName="rebuildElement";
00319 CSLAF *laf = CSLAF::getCurrentLAF();
00320 if (mMore)
00321 {
00322 mMore->removeMessageListener(this);
00323 removeElement(mMore);
00324 delete (mMore);
00325 mMore = 0;
00326 }
00327
00328 mMore = new CSButton(laf->getIcon(LAF_ICON_TYPE_DOWN));
00329
00330 CSLayoutData layoutData = mMore->getLayoutData();
00331 layoutData.setSpacing(0,0);
00332 layoutData.setCenteredHorizontal(false);
00333 mMore->setLayoutData(layoutData);
00334 mMore->setActionId(COMBOBOX_BUTTON_MORE_ACTION_ID);
00335 mMore->addMessageListener(this, GUI_MESSAGE);
00336 addElement(mMore, POSITION_EAST);
00337
00338 if (mListbox)
00339 {
00340 mListbox->removeMessageListener(this);
00341 removeElement(mListbox);
00342 delete (mListbox);
00343 mListbox = 0;
00344 }
00345 mListbox = new CSListbox(laf->getComboboxItemsShown(), mWidth);
00346 mListbox->setFocusable(false);
00347 mListbox->addMessageListener(this, GUI_MESSAGE);
00348 mListbox->setItemsShown(laf->getComboboxItemsShown());
00349 mListbox->setVisible(false);
00350 mListbox->setHoverSelection(true);
00351 }
00352
00353 void CSCombobox::layoutSetupCombobox()
00354 {
00355 static char *functionName="layoutSetupCombobox";
00356 CSLAF *laf = CSLAF::getCurrentLAF();
00357 mComboBoxInset = CSInset(2);
00358
00359 mTextOffset = 0;
00360 mHeight = getFont()->getHeight() + mComboBoxInset.getTotalHeight();
00361 if (mHeight < mMore->getHeight())
00362 {
00363 mHeight = mMore->getHeight();
00364 mTextOffset = (mMore->getHeight() - mHeight)/2;
00365 }
00366 mMinHeight = mHeight;
00367 mHeight += getBorder()->getTotalHeight() + mInset.getTotalHeight();
00368 mMinWidth = mWidth - getBorder()->getTotalWidth() + mInset.getTotalWidth();;
00369 }
00370
00371