@@ -30,6 +30,7 @@ class TextListComponent : public IList<TextListData, T>
3030 using IList<TextListData, T>::getTransform;
3131 using IList<TextListData, T>::mSize ;
3232 using IList<TextListData, T>::mCursor ;
33+ using IList<TextListData, T>::mViewportTop ;
3334 using IList<TextListData, T>::Entry;
3435
3536public:
@@ -92,7 +93,7 @@ class TextListComponent : public IList<TextListData, T>
9293 Alignment mAlignment ;
9394 float mHorizontalMargin ;
9495
95- int getFirstVisibleEntry ();
96+ int viewportTop ();
9697 std::function<void (CursorState state)> mCursorChangedCallback ;
9798
9899 std::shared_ptr<Font> mFont ;
@@ -107,10 +108,8 @@ class TextListComponent : public IList<TextListData, T>
107108 std::string mScrollSound ;
108109 static const unsigned int COLOR_ID_COUNT = 2 ;
109110 unsigned int mColors [COLOR_ID_COUNT];
110- unsigned int mScreenCount ;
111- int mStartEntry = 0 ;
112- unsigned int mCursorPrev = -1 ;
113- bool mOneEntryUpDn = true ;
111+ int mViewportHeight ;
112+ int mCursorPrev = -1 ;
114113
115114 ImageComponent mSelectorImage ;
116115};
@@ -151,32 +150,33 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
151150
152151 const float entrySize = Math::max (font->getHeight (1.0 ), (float )font->getSize ()) * mLineSpacing ;
153152
154- // number of entries that can fit on the screen simultaniously
155- mScreenCount = (int )(mSize .y () / entrySize);
153+ // number of listentries that can fit on the screen
154+ mViewportHeight = (int )(mSize .y () / entrySize);
156155
156+ if (mViewportTop == -1 )
157+ {
158+ // returning from screen saver activated game launch
159+ mViewportTop = mCursor - mViewportHeight /2 ;
160+ }
157161 if (mCursor != mCursorPrev )
158162 {
159- mStartEntry = (size () > mScreenCount ) ? getFirstVisibleEntry () : 0 ;
163+ mViewportTop = (size () > mViewportHeight ) ? viewportTop () : 0 ;
160164 mCursorPrev = mCursor ;
161165 }
162166
163- unsigned int listCutoff = mStartEntry + mScreenCount ;
167+ unsigned int listCutoff = mViewportTop + mViewportHeight ;
164168 if (listCutoff > size ())
165169 listCutoff = size ();
166170
167- float y = (mSize .y () - (mScreenCount * entrySize)) * 0 .5f ;
171+ float y = (mSize .y () - (mViewportHeight * entrySize)) * 0 .5f ;
168172
169- // draw selector bar
170- if (mStartEntry < listCutoff)
171- {
172- if (mSelectorImage .hasImage ()) {
173- mSelectorImage .setPosition (0 .f , y + (mCursor - mStartEntry )*entrySize + mSelectorOffsetY , 0 .f );
174- mSelectorImage .render (trans);
175- } else {
176- Renderer::setMatrix (trans);
177- Renderer::drawRect (0 .0f , y + (mCursor - mStartEntry )*entrySize + mSelectorOffsetY , mSize .x (),
178- mSelectorHeight , mSelectorColor , mSelectorColorEnd , mSelectorColorGradientHorizontal );
179- }
173+ if (mSelectorImage .hasImage ()) {
174+ mSelectorImage .setPosition (0 .f , y + (mCursor - mViewportTop )*entrySize + mSelectorOffsetY , 0 .f );
175+ mSelectorImage .render (trans);
176+ } else {
177+ Renderer::setMatrix (trans);
178+ Renderer::drawRect (0 .0f , y + (mCursor - mViewportTop )*entrySize + mSelectorOffsetY , mSize .x (),
179+ mSelectorHeight , mSelectorColor , mSelectorColorEnd , mSelectorColorGradientHorizontal );
180180 }
181181
182182 // clip to inside margins
@@ -185,7 +185,7 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
185185 Renderer::pushClipRect (Vector2i ((int )(trans.translation ().x () + mHorizontalMargin ), (int )trans.translation ().y ()),
186186 Vector2i ((int )(dim.x () - mHorizontalMargin *2 ), (int )dim.y ()));
187187
188- for (int i = mStartEntry ; i < listCutoff; i++)
188+ for (int i = mViewportTop ; i < listCutoff; i++)
189189 {
190190 typename IList<TextListData, T>::Entry& entry = mEntries .at ((unsigned int )i);
191191
@@ -254,91 +254,65 @@ void TextListComponent<T>::render(const Transform4x4f& parentTrans)
254254
255255
256256template <typename T>
257- int TextListComponent<T>::getFirstVisibleEntry ()
257+ int TextListComponent<T>::viewportTop ()
258258{
259+ int viewportTopMax = size () - mViewportHeight ;
260+ int topNew = mViewportTop ;
261+
259262 if (mCursorPrev == -1 )
260- {
261- // init or returned from emulator
262263 mCursorPrev = mCursor ;
263- int quot = div (mCursor , mScreenCount ).quot ;
264- mStartEntry = quot * mScreenCount ;
265- }
266- int screenRelCursor = mCursorPrev - mStartEntry ;
267- bool cursorCentered = screenRelCursor == mScreenCount /2 ;
268- int visibleEntryMax = size () - mScreenCount ;
269- int firstVisibleEntry = 0 ;
270264
271- if (Settings::getInstance ()->getBool (" UseFullscreenPaging" ) && !cursorCentered)
265+ int delta = mCursor - mCursorPrev ;
266+
267+ if (Settings::getInstance ()->getBool (" UseFullscreenPaging" ))
272268 {
273- // keep visible cursor constant but move visible list (default)
274- firstVisibleEntry = mCursor - screenRelCursor;
275- if (mOneEntryUpDn )
269+ // delta may be greater/less than +/-mViewportHeight on re-sorting of list
270+ if (delta <= -mViewportHeight || delta >= mViewportHeight
271+ // keep cursor sticky at position unless the user navigates
272+ // to the middle of the viewport
273+ || delta < 0 && mCursor - mViewportTop < mViewportHeight /2
274+ || delta > 0 && mCursor - mViewportTop > mViewportHeight /2 )
276275 {
277- int delta = mCursor - mCursorPrev ;
278- // detect rollover (== delta is more than one item)
279- if (delta < -3 )
280- firstVisibleEntry = 0 ;
281- else if (delta > 3 )
282- firstVisibleEntry = visibleEntryMax;
283- else if (screenRelCursor < mScreenCount /2 && delta > 0 /* down pressed*/
284- || screenRelCursor > mScreenCount /2 && delta < 0 /* up pressed*/ )
285- // cases for list begin / list end
286- // move visible cursor and keep visible list section constant
287- firstVisibleEntry = firstVisibleEntry - delta;
276+ topNew += delta;
288277 }
289- } else {
290- // cursor always in middle of visible list
291- firstVisibleEntry = mCursor - mScreenCount /2 ;
278+ // no match above will place the cursor more towards the middle
292279 }
293- // bounds check
294- if (firstVisibleEntry < 0 )
295- firstVisibleEntry = 0 ;
296- else if (firstVisibleEntry > visibleEntryMax)
297- firstVisibleEntry = visibleEntryMax;
298- return firstVisibleEntry;
280+ else
281+ // put cursor in middle of visible list
282+ topNew = mCursor - mViewportHeight /2 ;
283+
284+ if (mCursor <= mViewportHeight /2 )
285+ topNew = 0 ;
286+ else if (mCursor >= viewportTopMax + mViewportHeight /2 )
287+ topNew = viewportTopMax;
288+
289+ return topNew;
299290}
300291
301292template <typename T>
302293bool TextListComponent<T>::input(InputConfig* config, Input input)
303294{
304- if (size () > 0 )
295+ bool isSingleStep = config->isMappedLike (" down" , input) || config->isMappedLike (" up" , input);
296+ bool isPageStep = config->isMappedLike (" rightshoulder" , input) || config->isMappedLike (" leftshoulder" , input);
297+
298+ if (size () > 0 && (isSingleStep || isPageStep))
305299 {
306300 if (input.value != 0 )
307301 {
308- if (config->isMappedLike (" down" , input))
309- {
310- listInput (1 );
311- mOneEntryUpDn = true ;
312- return true ;
313- }
314-
315- if (config->isMappedLike (" up" , input))
316- {
317- listInput (-1 );
318- mOneEntryUpDn = true ;
319- return true ;
320- }
321- if (config->isMappedLike (" rightshoulder" , input))
322- {
323- int delta = Settings::getInstance ()->getBool (" UseFullscreenPaging" ) ? mScreenCount : 10 ;
324- listInput (delta);
325- mOneEntryUpDn = false ;
326- return true ;
327- }
328-
329- if (config->isMappedLike (" leftshoulder" , input))
302+ int delta;
303+ mCursorPrev = mCursor ;
304+ if (isSingleStep)
305+ delta = config->isMappedLike (" down" , input) ? 1 : -1 ;
306+ else
330307 {
331- int delta = Settings::getInstance ()->getBool (" UseFullscreenPaging" ) ? mScreenCount : 10 ;
332- listInput (-delta);
333- mOneEntryUpDn = false ;
334- return true ;
308+ delta = Settings::getInstance ()->getBool (" UseFullscreenPaging" ) ? mViewportHeight : 10 ;
309+ if (config->isMappedLike (" leftshoulder" , input))
310+ delta = -delta;
335311 }
312+ listInput (delta);
313+ return true ;
336314 }else {
337- if (config->isMappedLike (" down" , input) || config->isMappedLike (" up" , input) ||
338- config->isMappedLike (" rightshoulder" , input) || config->isMappedLike (" leftshoulder" , input))
339- {
340- stopScrolling ();
341- }
315+ stopScrolling ();
342316 }
343317 }
344318
0 commit comments