-
Notifications
You must be signed in to change notification settings - Fork 157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can TDialog have scrollable content ? #169
Comments
Hi @msilewicz! Sorry for the late reply. No, Turbo Vision does not provide any standard way to do what you say, even though it would be the only way to ensure your dialog can be used regardless of the terminal size. TScroller can't be used for this purpose because it is not a #define Uses_TScrollBar
#define Uses_TGroup
#define Uses_TKeys
#define Uses_TEvent
#include <tvision/tv.h>
class TScrollArea : public TGroup
{
public:
TScrollArea( const TRect &bounds,
TScrollBar *aHScrollBar = nullptr,
TScrollBar *aVScrollBar = nullptr
);
void setScrollLimits(int x, int y);
void changeBounds(const TRect &bounds) override;
void handleEvent(TEvent &event) override;
private:
TPoint scrollPosition {0, 0};
TPoint scrollLimit {0, 0};
TScrollBar *hScrollBar;
TScrollBar *vScrollBar;
TView *background;
void updateScrollBars();
void scrollTo(int, int);
static void adjustSubviewPosition(TView *, void *);
};
TScrollArea::TScrollArea( const TRect &bounds,
TScrollBar *aHScrollBar,
TScrollBar *aVScrollBar ) :
TGroup(bounds),
hScrollBar(aHScrollBar),
vScrollBar(aVScrollBar)
{
background = new TView(getExtent());
background->growMode = gfGrowHiX | gfGrowHiY;
insert(background);
}
void TScrollArea::setScrollLimits(int x, int y)
{
scrollLimit = {x, y};
updateScrollBars();
}
void TScrollArea::changeBounds(const TRect &bounds)
{
TGroup::changeBounds(bounds);
updateScrollBars();
}
void TScrollArea::handleEvent(TEvent &event)
{
TGroup::handleEvent(event);
if (event.what == evBroadcast)
{
if (event.message.command == cmScrollBarChanged)
{
if (hScrollBar && event.message.infoPtr == hScrollBar)
scrollTo(hScrollBar->value, scrollPosition.y);
else if (vScrollBar && event.message.infoPtr == vScrollBar)
scrollTo(scrollPosition.x, vScrollBar->value);
}
}
else if (event.what == evKeyDown)
{
switch (event.keyDown.keyCode)
{
case kbTab:
focusNext(false);
clearEvent(event);
break;
case kbShiftTab:
focusNext(true);
clearEvent(event);
break;
}
}
}
void TScrollArea::updateScrollBars()
{
if (hScrollBar)
hScrollBar->setParams( scrollPosition.x,
0,
scrollLimit.x - size.x,
size.x - 1,
hScrollBar->arStep
);
if (vScrollBar)
vScrollBar->setParams( scrollPosition.y,
0,
scrollLimit.y - size.y,
size.y - 1,
vScrollBar->arStep
);
}
void TScrollArea::scrollTo(int x, int y)
{
x = max(0, min(x, scrollLimit.x));
y = max(0, min(y, scrollLimit.y));
if (x != scrollPosition.x || y != scrollPosition.y)
{
TPoint delta = {
x - scrollPosition.x,
y - scrollPosition.y,
};
scrollPosition.x = x;
scrollPosition.y = y;
lock();
forEach(&adjustSubviewPosition, &delta);
unlock();
}
}
void TScrollArea::adjustSubviewPosition(TView *view, void *deltaPtr)
{
TPoint &delta = *(TPoint *) deltaPtr;
TScrollArea *self = (TScrollArea *) view->owner;
if (view != self->background)
{
view->origin.x -= delta.x;
view->origin.y -= delta.y;
}
view->drawView();
} For example, this is how it would be used in the greeting dialog of hello.cpp: void THelloApp::greetingBox()
{
TDialog *d = new TDialog(TRect( 25, 5, 55, 16 ), "Hello, World!" );
// Make the dialog resizable.
d->flags |= wfGrow;
// Create scrollbars.
TScrollBar *hScrollBar = d->standardScrollBar(sbHorizontal | sbHandleKeyboard);
TScrollBar *vScrollBar = d->standardScrollBar(sbVertical | sbHandleKeyboard);
// Insert a scroll area into the dialog.
TRect dialogInterior = d->getExtent().grow(-1,-1);
TScrollArea *scrollArea = new TScrollArea(dialogInterior, hScrollBar, vScrollBar);
scrollArea->growMode = gfGrowHiX | gfGrowHiY;
d->insert(scrollArea);
// Insert the views into the scroll area.
scrollArea->insert(new TStaticText(TRect(2, 4, 14, 5), "How are you?"));
scrollArea->insert(new TButton(TRect(15, 1, 27, 3), "Terrific", cmCancel, bfNormal));
scrollArea->insert(new TButton(TRect(15, 3, 27, 5), "Ok", cmCancel, bfNormal));
scrollArea->insert(new TButton(TRect(15, 5, 27, 7), "Lousy", cmCancel, bfNormal));
scrollArea->insert(new TButton(TRect(15, 7, 27, 9), "Cancel", cmCancel, bfNormal));
scrollArea->setScrollLimits(27, 9);
deskTop->execView(d);
destroy(d);
} And this is how the above looks like when the dialog gets downsized: I guess that it would be better if the scroll bars weren't shown at all unless scrolling is possible, but that would also require creating a different scrollbar implementation. |
Thank You very much for Your detailed answer. It was very helpful. Your example perfectly fits my needs as it comes to dialog scrollable area. |
I'm trying to figure out whether TDialog can have scrollable content that contains some input controls ?
How to achieve this ?
I don't know how to add for example TInputLine to TScroller ?
The text was updated successfully, but these errors were encountered: