133 | 133 | CRect COList::GetListRect() const |
134 | 134 | { |
135 | 135 | return m_CachedActualSize + CRect(0, m_HeadingHeight, 0, 0); |
136 | 136 | } |
137 | 137 | |
138 | 138 | void COList::HandleMessage(SGUIMessage& Message) |
139 | 139 | { |
140 | 140 | CList::HandleMessage(Message); |
141 | 141 | |
142 | 142 | switch (Message.type) |
143 | 143 | { |
144 | 144 | // If somebody clicks on the column heading |
145 | 145 | case GUIM_MOUSE_PRESS_LEFT: |
146 | 146 | { |
147 | 147 | bool sortable; |
148 | 148 | GUI<bool>::GetSetting(this, "sortable", sortable); |
149 | 149 | if (!sortable) |
150 | 150 | return; |
151 | 151 | |
152 | 152 | CPos mouse = GetMousePos(); |
153 | 153 | if (!m_CachedActualSize.PointInside(mouse)) |
154 | 154 | return; |
155 | 155 | |
156 | 156 | float xpos = 0; |
157 | 157 | for (size_t def = 0; def < m_ObjectsDefs.size(); ++def) |
158 | 158 | { |
159 | 159 | float width = m_ObjectsDefs[def].m_Width; |
160 | 160 | // Check if it's a decimal value, and if so, assume relative positioning. |
161 | 161 | if (m_ObjectsDefs[def].m_Width < 1 && m_ObjectsDefs[def].m_Width > 0) |
162 | 162 | width *= m_TotalAvalibleColumnWidth; |
164 | 164 | if (mouse.x >= leftTopCorner.x && |
165 | 165 | mouse.x < leftTopCorner.x + width && |
166 | 166 | mouse.y < leftTopCorner.y + m_HeadingHeight) |
167 | 167 | { |
168 | 168 | if (def != m_SelectedDef) |
169 | 169 | { |
170 | 170 | m_SelectedColumnOrder = 1; |
171 | 171 | m_SelectedDef = def; |
172 | 172 | } |
173 | 173 | else |
174 | 174 | m_SelectedColumnOrder = -m_SelectedColumnOrder; |
175 | 175 | GUI<CStr>::SetSetting(this, "selected_column", m_ObjectsDefs[def].m_Id.substr(5)); |
176 | 176 | GUI<int>::SetSetting(this, "selected_column_order", m_SelectedColumnOrder); |
177 | 177 | GUI<int>::SetSetting(this, "selected_def", def); |
178 | 178 | ScriptEvent("selectioncolumnchange"); |
179 | 179 | |
180 | 180 | CStrW soundPath; |
181 | 181 | if (g_SoundManager && GUI<CStrW>::GetSetting(this, "sound_selected", soundPath) == PSRETURN_OK && !soundPath.empty()) |
182 | 182 | g_SoundManager->PlayAsUI(soundPath.c_str(), false); |
183 | 183 | |
184 | 184 | return; |
185 | 185 | } |
186 | 186 | xpos += width; |
187 | 187 | } |
188 | 188 | return; |
189 | 189 | } |
190 | 190 | default: |
191 | 191 | return; |
192 | 192 | } |
193 | 193 | } |
294 | 294 | float bz = GetBufferedZ(); |
295 | 295 | |
296 | 296 | // First call draw on ScrollBarOwner |
297 | 297 | bool scrollbar; |
298 | 298 | GUI<bool>::GetSetting(this, "scrollbar", scrollbar); |
299 | 299 | |
300 | 300 | if (scrollbar) |
301 | 301 | IGUIScrollBarOwner::Draw(); |
302 | 302 | |
303 | 303 | if (!GetGUI()) |
304 | 304 | return; |
305 | 305 | |
306 | 306 | CRect rect = GetListRect(); |
307 | 307 | |
308 | 308 | CGUISpriteInstance* sprite = NULL; |
309 | 309 | CGUISpriteInstance* sprite_selectarea = NULL; |
310 | 310 | int cell_id; |
311 | 311 | GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite, sprite); |
312 | 312 | GUI<CGUISpriteInstance>::GetSettingPointer(this, _sprite_selected, sprite_selectarea); |
313 | 313 | GUI<int>::GetSetting(this, "cell_id", cell_id); |
314 | 314 | |
315 | 315 | CGUIList* pList; |
316 | 316 | GUI<CGUIList>::GetSettingPointer(this, "list_name", pList); |
317 | 317 | |
318 | 318 | GetGUI()->DrawSprite(*sprite, cell_id, bz, rect); |
319 | 319 | |
320 | 320 | float scroll = 0.f; |
321 | 321 | if (scrollbar) |
322 | 322 | scroll = GetScrollBar(0).GetPos(); |
323 | 323 | |
324 | 325 | if (selected != -1) |
325 | 326 | { |
326 | 327 | ENSURE(selected >= 0 && selected+1 < (int)m_ItemsYPositions.size()); |
327 | 328 | |
328 | 329 | // Get rectangle of selection: |
329 | 330 | CRect rect_sel(rect.left, rect.top + m_ItemsYPositions[selected] - scroll, |
330 | 331 | rect.right, rect.top + m_ItemsYPositions[selected+1] - scroll); |
331 | 332 | |
332 | 333 | if (rect_sel.top <= rect.bottom && |
333 | 334 | rect_sel.bottom >= rect.top) |
334 | 335 | { |
335 | 336 | if (rect_sel.bottom > rect.bottom) |
336 | 337 | rect_sel.bottom = rect.bottom; |
337 | 338 | if (rect_sel.top < rect.top) |
338 | 339 | rect_sel.top = rect.top; |
339 | 340 | |
340 | 341 | if (scrollbar) |
341 | 342 | { |
342 | 343 | // Remove any overlapping area of the scrollbar. |
343 | 344 | if (rect_sel.right > GetScrollBar(0).GetOuterRect().left && |
344 | 345 | rect_sel.right <= GetScrollBar(0).GetOuterRect().right) |
345 | 346 | rect_sel.right = GetScrollBar(0).GetOuterRect().left; |
346 | 347 | |
347 | 348 | if (rect_sel.left >= GetScrollBar(0).GetOuterRect().left && |
348 | 349 | rect_sel.left < GetScrollBar(0).GetOuterRect().right) |
349 | 350 | rect_sel.left = GetScrollBar(0).GetOuterRect().right; |
350 | 351 | } |
351 | 352 | |
359 | 362 | CGUISpriteInstance* sprite_heading = NULL; |
360 | 363 | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_heading", sprite_heading); |
361 | 364 | CRect rect_head(m_CachedActualSize.left, m_CachedActualSize.top, m_CachedActualSize.right, |
362 | 365 | m_CachedActualSize.top + m_HeadingHeight); |
363 | 366 | GetGUI()->DrawSprite(*sprite_heading, cell_id, bz, rect_head); |
364 | 367 | |
365 | 368 | CGUISpriteInstance* sprite_order; |
366 | 369 | CGUISpriteInstance* sprite_not_sorted; |
367 | 370 | if (m_SelectedColumnOrder != -1) |
368 | 371 | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_asc", sprite_order); |
369 | 372 | else |
370 | 373 | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_desc", sprite_order); |
371 | 374 | GUI<CGUISpriteInstance>::GetSettingPointer(this, "sprite_not_sorted", sprite_not_sorted); |
372 | 375 | |
394 | 403 | const size_t objectsCount = m_ObjectsDefs.size(); |
395 | 404 | for (size_t i = 0; i < pList->m_Items.size(); ++i) |
396 | 405 | { |
397 | 406 | if (m_ItemsYPositions[i+1] - scroll < 0 || |
398 | 407 | m_ItemsYPositions[i] - scroll > rect.GetHeight()) |
399 | 408 | continue; |
400 | 409 | |
401 | 410 | const float rowHeight = m_ItemsYPositions[i+1] - m_ItemsYPositions[i]; |
402 | 411 | |
403 | 412 | // Clipping area (we'll have to substract the scrollbar) |
404 | 413 | CRect cliparea = GetListRect(); |
405 | 414 | |
406 | 415 | if (scrollbar) |
407 | 416 | { |
408 | 417 | if (cliparea.right > GetScrollBar(0).GetOuterRect().left && |
409 | 418 | cliparea.right <= GetScrollBar(0).GetOuterRect().right) |
410 | 419 | cliparea.right = GetScrollBar(0).GetOuterRect().left; |
411 | 420 | |
412 | 421 | if (cliparea.left >= GetScrollBar(0).GetOuterRect().left && |
413 | 422 | cliparea.left < GetScrollBar(0).GetOuterRect().right) |
414 | 423 | cliparea.left = GetScrollBar(0).GetOuterRect().right; |
415 | 424 | } |
416 | 425 | |
417 | 427 | xpos = 0; |
418 | 428 | for (size_t def = 0; def < objectsCount; ++def) |
419 | 429 | { |
420 | 430 | // Determine text position and width |
421 | 431 | const CPos textPos = rect.TopLeft() + CPos(xpos, -scroll + m_ItemsYPositions[i]); |
422 | 432 | |
423 | 433 | float width = m_ObjectsDefs[def].m_Width;; |
424 | 434 | // Check if it's a decimal value, and if so, assume relative positioning. |
425 | 435 | if (m_ObjectsDefs[def].m_Width < 1 && m_ObjectsDefs[def].m_Width > 0) |
426 | 436 | width *= m_TotalAvalibleColumnWidth; |
427 | 437 | |
428 | 438 | // Clip text to the column (to prevent drawing text into the neighboring column) |
429 | 439 | CRect cliparea2 = cliparea; |
430 | 440 | cliparea2.right = std::min(cliparea2.right, textPos.x + width); |
431 | 441 | cliparea2.bottom = std::min(cliparea2.bottom, textPos.y + rowHeight); |
432 | 442 | |