Listbox Design Challenge

Here’s a coding challenge.

This is a desktop app I’m working on:

The top area (Top Categories, Budget), is a canvas.

The bottom area with the dates and items, is a custom listbox.

The top area takes up too much space to always be on screen. When the user scrolls, the top area should scroll off the screen to make room for the listbox below. That is, using the scroll wheel causes the listbox to move up and more entries to appear and the top area to disappear. Pretty much as you’d expect on a web page.

This listbox could have thousands of rows so it’s likely not conceivable to have it starting out expanded but off screen. Unless Xojo is particularly good at not updating off screen listbox stuff.

I could throw everything on a canvas or container control, trap the scrolling event, and move the top area up and the listbox up as needed. However I suspect Xojo won’t work smoothly with that particularly on Windows.

My only idea is to have a custom listbox that has the first dozen rows reserved for drawing my top canvas row by row. Not terribly pretty to implement. However, that will mean that both top and bottom area scroll smoothly together as they are part of one listbox.

Anyone have a clever idea on how to better pull this off?

OK - it’s early in the morning, and I haven’t given this any time - but one idea that popped in my head was this:

  1. Detect if listbox has been scrolled (Listbox.MouseWheel)
  2. See what the listbox scroll position is (Listbox.ScrollPosition)
  3. If scrolled enough, then hide or shrink the canvas and extend the listbox up to include the upper portion of the screen

There may be lots of reasons why this is a bad idea, but nevertheless, it is an idea.

Good luck - the app has a nice look to it.

In rereading your post - I may have pretty much restated your idea, except I didn’t think is all needed to be in the same container to pull it off.

That should be relatively easy.

Add 12 Blank line to the listbox first.

In CellBackgroundPaint

[code]Dim HeaderPosition as integer = row - me.ScrollPostion

If HeaderPosition < 12 Then
’ Draw header info for that header line
Return True
End if

BTW thousands of rows in a listbox is not so user friendly IMO… Maybe you might want to consider using hierarchical listbox and grouping the entries older than a week or 2 by month and if older than say 6 months by quarter?

That way the user can expand the details for the time period they care about.

  • Karen

I would design the whole thing as a canvas and throw it in a NSScrollView (which is a different topic for a different day). You can then use the Areas array to draw only what needs to be onscreen at the time.

Umm, I think he needs Windows too …

Interesting, how can you put a canvas into a NSScrollView? Any example would do. :slight_smile:

I think that there are three potential ways of doing it.

  1. As Mark P suggests, as the first e.g. 200px of the list box is scrolled, gradually ‘roll up’ the top canvas.
  2. Have the two things as separate items on a Canvas, and scroll that canvas.
  3. Paint the top control in the first x rows of your listbox.

2 and 3 are functionally indistinguishable.

1: I think this could look a bit weird if the top control is half rolled up - would it be usable? How would the user realise that they needed to scroll the bottom list box back down to get the canvas back? I’m not keen on this, despite at first glance thinking it would look really cool.

2/3: This makes much more sense from a behavioural point of view. 3 instinctively feels like a fudge, but it would mean that your listbox was handling all the scrolling for you so you didn’t need to make your own scrollbar. 2 is neater but harder.


would something like this not work?

if window.scrollvalue > toplist.height then

toplist.visible = false = 0

else = top list.height
toplist.visible = true

end if

One other Idea… and I think it’s better than putting everything in a listbox

Put the Top part in canvas but use a disclosure widget. When the user clicks to close it shrinks to single line and teh listbox resizes to use the extra vertical space:

V Summary
Top Categories Budget
* Design Time Amt $

It would, but that would mean a jump in listbox position (surprising to the user) and no visual clues for how to get the top list back. At least with a scrollbar (like in points 2 and 3 above) there’s a visual clue that there’s information which has gone off the top of the screen.
Karen: That would give the user control over whether they can see the top list all the time or not, and user control is good, so I should definitely have included that in the options.

Hit post by accident too soon.

One other Idea… and I think it’s better than putting everything in a listbox

Put the Top part in canvas but use a disclosure widget. When the user clicks to close it shrinks to single line and the listbox resizes to use the extra vertical space:

V Summary
Top Categories Budget
* Design Time Amt $ 6,800 <-> 10,200
* Meeting Time Amt
* Development

Detail ListBox

And Closed



Detail ListBox

You could scroll the canvas when the user hit more… OR make the listbox shorter depending on needs

That way the user can always easily expand the header without losing their place in the listbox. I think that is a better solution than scrolling the summary area off screen

  • Karen

Hi Hamish,

well, i like to leave my users with a feeling of ‘quoi’ :wink:

Ha! In that case, you could always just randomise all your controls’ top and left properties on load, as well? :wink:

having the type of users that go home on Friday night able to do the job well, and arrive on Monday morning only vaguely aware of their own names, i suspect they would not notice, and not care.

i have some users with 15 years served who still use a small spiral bound bible notebook EVERY time they perform a process.

if the third box down changed to read ‘do you wish to apply a large electric shock to your chair’ they would put ‘Y’ in it, if the bible told them to.

@Karen. Yes, thousands of rows is not the best but if you are careful with what you’re doing, it’s not too much of a speed issue and the user only sees them if they scroll the listbox. Am considering limiting them and have a “See more”.

@Sam. I can’t redo the listbox portion as a canvas. Too much code invested in listbox already.

@Karen. I’d prefer not to have my users explicitly close the upper area. Better for it to scroll off the screen like a web page that people are used to.

@Russ. Ha!

@Hamish and others:

Can Xojo do this kind of control moves smoothly enough? Flicker free on Windows?

[quote]2. Have the two things as separate items on a Canvas, and scroll that canvas.

While I can see this scrolling static controls, won’t this run into a problem in that the listbox needs to scroll too? Won’t the listbox capture the canvas scroll if the user is moused over? And how does a scroll event in the canvas translate to a scroll of the listbox?

This seems the most viable so far.

Hi there:
1: You’d probably get a bit of flicker on Windows.
2: Here, you’d make the listbox height to be the full height of the whole of its contents (i.e. if it’s 2k rows and 22px per row you’d have it being 4400px high) and scroll the canvas only, not scroll the listbox.
3. Yep, I agree, but it does feel a bit like it’s the least worst option, rather than the best.

Well you can update it and OS X compositing engine takes care of not drawing it since it is off screen.
Windows not so much BUT you can insert declares to freeze screen updates & release them to make it flicker less. (see WFS FreezeUpdate / UnfreezeUpdate )

I’m an experienced developer but new to Xojo/RB. In the Xojo Web App world, there’s the WebContainer that would handle that with no code. There’s no container like that in the Xojo Desktop App world?

[By the way, I really like the style of that form. Looks great.]