-
|
I'm trying to figure out whether TDialog can have scrollable content that contains some input controls ? |
Beta Was this translation helpful? Give feedback.
Replies: 4 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. |
Beta Was this translation helpful? Give feedback.
-
|
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. |
Beta Was this translation helpful? Give feedback.

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
TGroupand it is therefore not meant to contain other views. However, it is possible to write a class which does this. A possible basic implementation: