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
Fix issue 1199 sitrep list lacks scroll bar for last item. #1356
Changes from 4 commits
474cbff
8c1b055
2fb4d05
cede324
21ba245
10753fb
af968ac
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -544,16 +544,19 @@ class GG_API ListBox : public Control | |
Row& ColHeaders(); ///< returns the row containing the headings for the columns, if any. If undefined, the returned heading Row will have size() 0. non-const for derivers | ||
//@} | ||
|
||
void AdjustScrolls(bool adjust_for_resize); ///< creates, destroys, or resizes scrolls to reflect size of data in listbox | ||
/** creates, destroys, or resizes scrolls to reflect size of data in listbox. \p force_scroll | ||
forces the scroll bar to be added.*/ | ||
void AdjustScrolls(bool adjust_for_resize, const std::pair<bool, bool>& force_scrolls = {false, false}); | ||
|
||
void DropsAcceptable(DropsAcceptableIter first, DropsAcceptableIter last, | ||
const Pt& pt, Flags<ModKey> mod_keys) const override; | ||
void HandleRowRightClicked(const Pt& pt, Flags<ModKey> mod); | ||
|
||
private: | ||
/** Show only rows that are within the visible list box area and hide all others. If | ||
\p do_prerender is true then prerender the visible rows.*/ | ||
void ShowVisibleRows(bool do_prerender); | ||
\p do_prerender is true then prerender the visible rows. Return true if prerender | ||
resulted in any visible row changing size. */ | ||
bool ShowVisibleRows(bool do_prerender); | ||
void ConnectSignals(); | ||
void ValidateStyle(); ///< reconciles inconsistencies in the style flags | ||
void VScrolled(int tab_low, int tab_high, int low, int high);///< signals from the vertical scroll bar are caught here | ||
|
@@ -569,6 +572,15 @@ class GG_API ListBox : public Control | |
/** Restore cached selected, clicked and last browsed rows.*/ | ||
void RestoreCachedSelections(const SelectionCache& cache); | ||
|
||
/** Return the client size excluding the scroll bar sizes.*/ | ||
Pt ClientSizeExcludingScrolls() const; | ||
/** Return a pair of dimensions of the scollable area if vscroll and/or hscroll is required.*/ | ||
std::pair<boost::optional<X>, boost::optional<Y>> | ||
CheckIfScrollsRequired(const std::pair<bool, bool>& force_scrolls= {false, false}) const; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. space b4 = There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
/** Add vscroll and/or hscroll if \p required_total_extents x or y dimension exists. Return a | ||
pair of bools indicating if added or removed vscroll or hscroll.*/ | ||
std::pair<bool, bool> AddOrRemoveScrolls(const std::pair<boost::optional<X>, boost::optional<Y>>& required_total_extents); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems like a rather odd function signature. why not take bools? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've expanded the descriptions in the functions which hopefully clarifies this. The client size excludes the scroll bar because it is the size used to decide is scroll bars are needed. The extent is the full size of the underlying list box, which will be larger than the client area unless the scrolls were force on. |
||
|
||
std::list<Row*> m_rows; ///< line item data | ||
|
||
Scroll* m_vscroll; ///< vertical scroll bar on right | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -853,20 +853,43 @@ void ListBox::PreRender() | |
NormalizeRow(row); | ||
} | ||
|
||
AdjustScrolls(false); | ||
|
||
// Reset require prerender after call to adjust scrolls | ||
Control::PreRender(); | ||
// Adding/removing scrolls and prerendering rows may change the row sizes and require a change | ||
// in added/removed scrolls. This may not be stable. Perform two cycles and if it is not | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prefer single space after . |
||
// stable then force the scrollbar to be added if either cycle had a scroll bar. | ||
|
||
// Perform a cycle of adjust scrolls and prerendering rows and return if sizes changed. | ||
auto check_adjust_scroll_size_change = | ||
[this] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please put the capture in front of the parameter list. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved. |
||
(std::pair<bool,bool> force_scrolls = {false, false}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. space after , There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
||
{ | ||
// This adjust scrolls may add or remove scrolls | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like unnecessary double indentation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am unsure of your meaning. What I see is,
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would de-indent everything from the { to the } line (inclusive). Right now, the actual function body is double-indented from the surrounding scope. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've changed the indenting. |
||
AdjustScrolls(true); | ||
|
||
// Resize rows to fit client area. | ||
X row_width(std::max(ClientWidth(), X(1))); | ||
for (Row* row : m_rows) | ||
row->Resize(Pt(row_width, row->Height())); | ||
bool visible_row_size_change = ShowVisibleRows(true); | ||
|
||
ShowVisibleRows(true); | ||
bool header_size_change = false; | ||
if (!m_header_row->empty()) { | ||
auto old_size = m_header_row->Size(); | ||
GUI::PreRenderWindow(m_header_row); | ||
header_size_change |= (old_size != m_header_row->Size()); | ||
} | ||
return visible_row_size_change | header_size_change; | ||
}; | ||
|
||
// Try adjusting scroll twice and then force the scrolls on. | ||
if (check_adjust_scroll_size_change()) { | ||
bool any_vscroll = (m_vscroll != nullptr); | ||
bool any_hscroll = (m_hscroll != nullptr); | ||
|
||
if (check_adjust_scroll_size_change()) { | ||
any_vscroll |= (m_vscroll != nullptr); | ||
any_hscroll |= (m_hscroll != nullptr); | ||
check_adjust_scroll_size_change({any_hscroll, any_vscroll}); | ||
} | ||
} | ||
|
||
if (!m_header_row->empty()) | ||
GUI::PreRenderWindow(m_header_row); | ||
// Reset require prerender after call to adjust scrolls | ||
Control::PreRender(); | ||
|
||
// Position rows | ||
Pt pt(m_first_row_offset); | ||
|
@@ -946,8 +969,9 @@ void ListBox::SizeMove(const Pt& ul, const Pt& lr) | |
RequirePreRender(); | ||
} | ||
|
||
void ListBox::ShowVisibleRows(bool do_prerender) | ||
bool ListBox::ShowVisibleRows(bool do_prerender) | ||
{ | ||
bool a_row_size_changed = false; | ||
// Ensure that data in occluded cells is not rendered | ||
// and that any re-layout during prerender is immediate. | ||
Y visible_height(BORDER_THICK); | ||
|
@@ -961,15 +985,19 @@ void ListBox::ShowVisibleRows(bool do_prerender) | |
(*it)->Hide(); | ||
} else { | ||
(*it)->Show(); | ||
if (do_prerender) | ||
if (do_prerender) { | ||
auto old_size = (*it)->Size(); | ||
GUI::PreRenderWindow(*it); | ||
a_row_size_changed |= (old_size != (*it)->Size()); | ||
} | ||
|
||
visible_height += (*it)->Height(); | ||
if (visible_height >= max_visible_height) | ||
hide = true; | ||
} | ||
} | ||
|
||
return a_row_size_changed; | ||
} | ||
|
||
void ListBox::Show(bool show_children /* = true*/) | ||
|
@@ -2122,7 +2150,18 @@ void ListBox::ValidateStyle() | |
m_style &= ~(LIST_NOSEL | LIST_SINGLESEL | LIST_QUICKSEL); | ||
} | ||
|
||
void ListBox::AdjustScrolls(bool adjust_for_resize) | ||
Pt ListBox::ClientSizeExcludingScrolls() const | ||
{ | ||
// this client area calculation disregards the thickness of scrolls | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. meaning of "disregards" is unclear. is the area smaller than the total client area by the scroll area? or is the presence or absence of scrolls irrelevant to the calculation? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I clarified the comment. |
||
Pt cl_sz = (LowerRight() - Pt(X(BORDER_THICK), Y(BORDER_THICK))) - | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the way the lines are broken here is confusing. prefer keeping a single expression together with linebreaks after a , There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried a different parsing so that each |
||
(UpperLeft() + Pt(X(BORDER_THICK), static_cast<int>(BORDER_THICK) | ||
+ (m_header_row->empty() | ||
? Y0 | ||
: m_header_row->Height()))); | ||
return cl_sz; | ||
} | ||
|
||
std::pair<boost::optional<X>, boost::optional<Y>> ListBox::CheckIfScrollsRequired(const std::pair<bool, bool>& force_scrolls) const | ||
{ | ||
// this client area calculation disregards the thickness of scrolls | ||
Pt cl_sz = (LowerRight() - Pt(X(BORDER_THICK), Y(BORDER_THICK))) - | ||
|
@@ -2137,11 +2176,13 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
total_y_extent += row->Height(); | ||
|
||
bool vertical_needed = | ||
force_scrolls.second || | ||
m_first_row_shown != m_rows.begin() || | ||
(m_rows.size() && (cl_sz.y < total_y_extent || | ||
(cl_sz.y < total_y_extent - SCROLL_WIDTH && | ||
cl_sz.x < total_x_extent - SCROLL_WIDTH))); | ||
bool horizontal_needed = | ||
force_scrolls.first || | ||
m_first_col_shown || | ||
(m_rows.size() && (cl_sz.x < total_x_extent || | ||
(cl_sz.x < total_x_extent - SCROLL_WIDTH && | ||
|
@@ -2161,15 +2202,30 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
total_y_extent += cl_sz.y - m_rows.back()->Height(); | ||
} | ||
|
||
std::shared_ptr<StyleFactory> style = GetStyleFactory(); | ||
boost::optional<X> x_retval = horizontal_needed ? boost::optional<X>(total_x_extent) : boost::none; | ||
boost::optional<Y> y_retval = vertical_needed ? boost::optional<Y>(total_y_extent) : boost::none; | ||
|
||
return {x_retval, y_retval}; | ||
} | ||
|
||
std::pair<bool, bool> ListBox::AddOrRemoveScrolls( | ||
const std::pair<boost::optional<X>, boost::optional<Y>>& required_total_extents) | ||
{ | ||
const std::shared_ptr<const StyleFactory> style = GetStyleFactory(); | ||
const Pt cl_sz = ClientSizeExcludingScrolls(); | ||
|
||
bool vscroll_added_or_removed(false); | ||
bool horizontal_needed = (required_total_extents.first ? true : false); | ||
X total_x_extent = required_total_extents.first ? *required_total_extents.first : X0; | ||
bool vertical_needed = (required_total_extents.second ? true : false); | ||
Y total_y_extent = required_total_extents.second ? *required_total_extents.second : Y0; | ||
|
||
bool vscroll_added_or_removed = false; | ||
|
||
// Remove unecessary vscroll | ||
if (m_vscroll && !vertical_needed) { | ||
vscroll_added_or_removed = true; | ||
DeleteChild(m_vscroll); | ||
m_vscroll = nullptr; | ||
vscroll_added_or_removed = true; | ||
} | ||
|
||
// Add necessary vscroll | ||
|
@@ -2185,14 +2241,6 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
} | ||
|
||
if (vertical_needed) { | ||
if (adjust_for_resize) { | ||
X scroll_x = cl_sz.x - SCROLL_WIDTH; | ||
Y scroll_y(0); | ||
m_vscroll->SizeMove(Pt(scroll_x, scroll_y), | ||
Pt(scroll_x + SCROLL_WIDTH, | ||
scroll_y + cl_sz.y - (horizontal_needed ? SCROLL_WIDTH : 0))); | ||
} | ||
|
||
unsigned int line_size = m_vscroll_wheel_scroll_increment; | ||
if (line_size == 0 && !this->Empty()) { | ||
const Row* row = *begin(); | ||
|
@@ -2207,14 +2255,18 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
MoveChildUp(m_vscroll); | ||
} | ||
|
||
bool hscroll_added_or_removed = false; | ||
|
||
// Remove unecessary hscroll | ||
if (m_hscroll && !horizontal_needed) { | ||
hscroll_added_or_removed = true; | ||
DeleteChild(m_hscroll); | ||
m_hscroll = nullptr; | ||
} | ||
|
||
// Add necessary hscroll | ||
if (!m_hscroll && horizontal_needed) { | ||
hscroll_added_or_removed = true; | ||
m_hscroll = style->NewListBoxHScroll(m_color, CLR_SHADOW); | ||
m_hscroll->NonClientChild(true); | ||
m_hscroll->MoveTo(Pt(X0, cl_sz.y - SCROLL_WIDTH)); | ||
|
@@ -2225,14 +2277,6 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
} | ||
|
||
if (horizontal_needed) { | ||
if (adjust_for_resize) { | ||
X scroll_x(0); | ||
Y scroll_y = cl_sz.y - SCROLL_WIDTH; | ||
m_hscroll->SizeMove(Pt(scroll_x, scroll_y), | ||
Pt(scroll_x + cl_sz.x - (vertical_needed ? SCROLL_WIDTH : 0), | ||
scroll_y + SCROLL_WIDTH)); | ||
} | ||
|
||
unsigned int line_size = m_hscroll_wheel_scroll_increment; | ||
if (line_size == 0 && !this->Empty()) { | ||
const Row* row = *begin(); | ||
|
@@ -2246,8 +2290,39 @@ void ListBox::AdjustScrolls(bool adjust_for_resize) | |
MoveChildUp(m_hscroll); | ||
} | ||
|
||
return {hscroll_added_or_removed, vscroll_added_or_removed}; | ||
} | ||
|
||
void ListBox::AdjustScrolls(bool adjust_for_resize, const std::pair<bool, bool>& force_scrolls) | ||
{ | ||
const auto required_total_extents = CheckIfScrollsRequired(force_scrolls); | ||
|
||
bool vscroll_added_or_removed; | ||
std::tie(std::ignore, vscroll_added_or_removed) = AddOrRemoveScrolls(required_total_extents); | ||
|
||
const Pt cl_sz = ClientSizeExcludingScrolls(); | ||
|
||
if (!adjust_for_resize) | ||
return; | ||
|
||
if (m_vscroll) { | ||
X scroll_x = cl_sz.x - SCROLL_WIDTH; | ||
Y scroll_y(0); | ||
m_vscroll->SizeMove(Pt(scroll_x, scroll_y), | ||
Pt(scroll_x + SCROLL_WIDTH, | ||
scroll_y + cl_sz.y - (m_hscroll ? SCROLL_WIDTH : 0))); | ||
} | ||
|
||
if (m_hscroll) { | ||
X scroll_x(0); | ||
Y scroll_y = cl_sz.y - SCROLL_WIDTH; | ||
m_hscroll->SizeMove(Pt(scroll_x, scroll_y), | ||
Pt(scroll_x + cl_sz.x - (m_vscroll ? SCROLL_WIDTH : 0), | ||
scroll_y + SCROLL_WIDTH)); | ||
} | ||
|
||
// Resize rows to fit client area. | ||
if (vscroll_added_or_removed || adjust_for_resize) { | ||
if (vscroll_added_or_removed) { | ||
RequirePreRender(); | ||
X row_width(std::max(ClientWidth(), X(1))); | ||
for (Row* row : m_rows) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this comment is unclear to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Expanded comment.