Skip to content
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

Improve resizing of contents with size hints #267

Merged
merged 2 commits into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Changelog {#changelog}

# Release 1.5 (git master)

* [267](https://github.com/BlueBrain/Tide/pull/267):
Improve resizing of external streams by better considering its size hints.
* [266](https://github.com/BlueBrain/Tide/pull/266):
Multiple bugfixes:
- Fix crashes in case of file read errors on some of the wall processes.
Expand Down
129 changes: 78 additions & 51 deletions tests/cpp/core/WindowControllerTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,30 +138,45 @@ WindowPtr makeDummyWindow()
return window;
}

BOOST_AUTO_TEST_CASE(testOneToOneSize)
struct TestFixture
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);
const QRectF& coords = window->getCoordinates();
WindowPtr window = makeDummyWindow();
DisplayGroupPtr displayGroup = DisplayGroup::create(wallSize);
WindowController controller{*window, *displayGroup};
};

BOOST_FIXTURE_TEST_CASE(testOneToOneSize, TestFixture)
{
controller.adjustSize(SIZE_1TO1);

// 1:1 size restored around existing window center
const auto& coords = window->getCoordinates();
BOOST_CHECK_EQUAL(coords.size(), CONTENT_SIZE);
BOOST_CHECK_EQUAL(coords.center(), QPointF(625, 240));
}

BOOST_AUTO_TEST_CASE(testOneToOneFittingSize)
BOOST_FIXTURE_TEST_CASE(testOneToOneSizeUsesPreferedSize, TestFixture)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);
const QRectF& coords = window->getCoordinates();
deflect::SizeHints hints;
hints.preferredWidth = CONTENT_SIZE.width() * 0.8;
hints.preferredHeight = CONTENT_SIZE.height() * 1.1;
window->getContent().setSizeHints(hints);

controller.adjustSize(SIZE_1TO1);

// 1:1 size restored around existing window center
const auto& coords = window->getCoordinates();
BOOST_CHECK_EQUAL(coords.size(),
QSizeF(hints.preferredWidth, hints.preferredHeight));
BOOST_CHECK_EQUAL(coords.center(), QPointF(625, 240));
}

BOOST_FIXTURE_TEST_CASE(testOneToOneFittingSize, TestFixture)
{
controller.adjustSize(SIZE_1TO1_FITTING);

// 1:1 size restored around existing window center
const auto& coords = window->getCoordinates();
BOOST_CHECK_EQUAL(coords.size(), CONTENT_SIZE);
BOOST_CHECK_EQUAL(coords.center(), QPointF(625, 240));

Expand All @@ -172,12 +187,8 @@ BOOST_AUTO_TEST_CASE(testOneToOneFittingSize)
BOOST_CHECK_EQUAL(coords.center(), QPointF(625, 240));
}

BOOST_AUTO_TEST_CASE(testSizeLimitsBigContent)
BOOST_FIXTURE_TEST_CASE(testSizeLimitsBigContent, TestFixture)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);

// Make a large content and validate it
auto& content = window->getContent();
content.setDimensions(BIG_CONTENT_SIZE);
Expand All @@ -198,12 +209,8 @@ BOOST_AUTO_TEST_CASE(testSizeLimitsBigContent)
BOOST_CHECK_EQUAL(controller.getMaxSize(), 0.25 * normalMaxSize);
}

BOOST_AUTO_TEST_CASE(testSizeLimitsSmallContent)
BOOST_FIXTURE_TEST_CASE(testSizeLimitsSmallContent, TestFixture)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);

// Make a small content and validate it
auto& content = window->getContent();
content.setDimensions(SMALL_CONTENT_SIZE);
Expand All @@ -218,18 +225,57 @@ BOOST_AUTO_TEST_CASE(testSizeLimitsSmallContent)
BOOST_CHECK_EQUAL(controller.getMaxSize(),
SMALL_CONTENT_SIZE * Content::getMaxScale());

const QSizeF normalMaxSize = controller.getMaxSize();
const auto normalMaxSize = controller.getMaxSize();
window->getContent().setZoomRect(
QRectF(QPointF(0.3, 0.1), QSizeF(0.25, 0.25)));
BOOST_CHECK_EQUAL(controller.getMaxSize(), 0.25 * normalMaxSize);
}

BOOST_AUTO_TEST_CASE(testAspectRatioMinSize)
BOOST_FIXTURE_TEST_CASE(smallContentMadeFullscreenRespectsMaxContentSize,
TestFixture)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);
auto& content = window->getContent();
content.setDimensions(SMALL_CONTENT_SIZE);

BOOST_REQUIRE(content.getMaxDimensions() < wallSize);

controller.adjustSize(SizeState::SIZE_FULLSCREEN);

BOOST_CHECK_EQUAL(window->getCoordinates().size(),
content.getMaxDimensions());
}

BOOST_FIXTURE_TEST_CASE(smallContentWithBigMaxSizeHintsCanBeMadeFullscreen,
TestFixture)
{
auto& content = window->getContent();
content.setDimensions(SMALL_CONTENT_SIZE);

deflect::SizeHints hints;
hints.maxWidth = std::numeric_limits<unsigned int>::max();
hints.maxHeight = std::numeric_limits<unsigned int>::max();
content.setSizeHints(hints);

BOOST_REQUIRE_EQUAL(content.getMaxDimensions(),
QSize(std::numeric_limits<int>::max(),
std::numeric_limits<int>::max()));

// Keep content aspect ratio
controller.adjustSize(SizeState::SIZE_FULLSCREEN);
BOOST_CHECK_EQUAL(window->getCoordinates(),
QRectF(QPointF{0, 125}, QSizeF{1000, 750}));

// Use preferred size aspect ratio
hints.preferredWidth = wallSize.width() / 2;
hints.preferredHeight = wallSize.height() / 2;
content.setSizeHints(hints);
controller.adjustSize(SizeState::SIZE_FULLSCREEN);
BOOST_CHECK_EQUAL(window->getCoordinates(),
QRectF(QPointF{0, 0}, wallSize));
}

BOOST_FIXTURE_TEST_CASE(testAspectRatioMinSize, TestFixture)
{
// Make a content and validate MinSize keeps aspect ratio
auto& content = window->getContent();
content.setDimensions(QSize(400, 800));
Expand Down Expand Up @@ -265,8 +311,8 @@ BOOST_AUTO_TEST_CASE(testAspectRatioMinSize)
QSize(600, 300));

window->setMode(Window::STANDARD);
const QSize maxSize(CONTENT_SIZE * 2);
const QSize minSize(CONTENT_SIZE / 2);
const auto maxSize = QSize{CONTENT_SIZE * 2};
const auto minSize = QSize{CONTENT_SIZE / 2};
deflect::SizeHints hints;
hints.maxWidth = maxSize.width();
hints.maxHeight = maxSize.height();
Expand All @@ -289,25 +335,21 @@ BOOST_AUTO_TEST_CASE(testAspectRatioMinSize)
QSize(400, 300));
}

BOOST_AUTO_TEST_CASE(testSizeHints)
BOOST_FIXTURE_TEST_CASE(testSizeHints, TestFixture)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);
auto& content = window->getContent();

const QSize maxSize(CONTENT_SIZE * 2);
const QSize minSize(CONTENT_SIZE / 2);
const auto maxSize = QSize{CONTENT_SIZE * 2};
const auto minSize = QSize{CONTENT_SIZE / 2};
deflect::SizeHints hints;
hints.maxWidth = maxSize.width();
hints.maxHeight = maxSize.height();
hints.minWidth = minSize.width();
hints.minHeight = minSize.height();
hints.preferredWidth = CONTENT_SIZE.width();
hints.preferredHeight = CONTENT_SIZE.height();
auto& content = window->getContent();
content.setSizeHints(hints);
content.setDimensions(CONTENT_SIZE);
const QRectF& coords = window->getCoordinates();
const auto& coords = window->getCoordinates();

// too big, constrains to maxSize
controller.resize(maxSize * 2, CENTER);
Expand All @@ -326,21 +368,6 @@ BOOST_AUTO_TEST_CASE(testSizeHints)
BOOST_CHECK_EQUAL(coords.size(), minSize);
}

BOOST_AUTO_TEST_CASE(testLargeSize)
{
auto window = makeDummyWindow();
auto displayGroup = DisplayGroup::create(wallSize);
WindowController controller(*window, *displayGroup);
const QRectF& coords = window->getCoordinates();

controller.adjustSize(SIZE_LARGE);

// 75% of the screen, resized around window center
BOOST_CHECK_EQUAL(coords.center(), QPointF(625, 240));
BOOST_CHECK_EQUAL(coords.width(), 0.75 * wallSize.width());
BOOST_CHECK_EQUAL(coords.height(), 0.75 * wallSize.width() / CONTENT_AR);
}

void _checkFullscreen(const QRectF& coords)
{
// full screen, center on wall
Expand Down
9 changes: 5 additions & 4 deletions tide/core/resources/WindowControls.qml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Item {
Rectangle {
id: buttonsRectangle
width: buttons.width + 2 * Style.buttonsPadding
height: buttons.height
height: triangle.visible ? buttons.height : buttons.height + 2 * Style.buttonsPadding
color: Style.controlsDefaultColor
}
Triangle {
Expand All @@ -25,6 +25,8 @@ Item {
height: 2 * width
color: buttonsRectangle.color
anchors.top: buttonsRectangle.bottom
visible: (window.focused ? window.focusedCoordinates.height : window.height)
> (buttons.height + triangle.height)
}

WindowControlButtons {
Expand All @@ -42,9 +44,8 @@ Item {
},
State {
name: "opaque"
when: window.selected &&
window.state !== Window.RESIZING &&
!window.fullscreen
when: window.selected && window.state !== Window.RESIZING
&& !window.fullscreen
PropertyChanges {
target: windowControls
opacity: 1
Expand Down
14 changes: 12 additions & 2 deletions tide/core/scene/Content.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@

IMPLEMENT_SERIALIZE_FOR_XML(Content)

namespace
{
int _clampToInt(const unsigned int n)
{
return std::min((unsigned int)std::numeric_limits<int>::max(), n);
}
}

qreal Content::_maxScale = 3.0;

Content::Content(const QString& uri)
Expand Down Expand Up @@ -127,20 +135,22 @@ QSize Content::getMaxDimensions() const
return getDimensions().isValid() ? getDimensions() * getMaxScale()
: UNDEFINED_SIZE;
}
return QSize(_sizeHints.maxWidth, _sizeHints.maxHeight);
return QSize{_clampToInt(_sizeHints.maxWidth),
_clampToInt(_sizeHints.maxHeight)};
}

void Content::setSizeHints(const deflect::SizeHints& sizeHints)
{
if (_sizeHints == sizeHints)
return;

_sizeHints = sizeHints;
emit modified();
}

void Content::setMaxScale(const qreal value)
{
if (value > 0)
if (value > 0.0)
_maxScale = value;
}

Expand Down
12 changes: 11 additions & 1 deletion tide/core/ui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ const qreal buttonsPadding = buttonsSize / 4.0;
const qreal buttonsSizeLarge = 1.15 * buttonsSize;
const qreal buttonsPaddingLarge = 1.15 * buttonsPadding;

/** Derived UI element sizes. */
const qreal movieBarHeight = buttonsSize;
const qreal controlsWidth = buttonsSize + 2 * buttonsPadding;
const qreal controlsDistanceFromWindow = buttonsPadding;

/** Constraints. */
const qreal minWindowSize = 300;
const qreal minWindowSpacingInFocusMode = 40;

inline bool hasMovieControls(const Content& content)
{
return content.getType() == ContentType::movie;
Expand All @@ -71,7 +76,7 @@ qreal getWindowControlsMargin()

qreal getMinWindowSpacing()
{
return 40.0;
return minWindowSpacingInFocusMode;
}

qreal getFocusedWindowControlBarHeight(const Content& content)
Expand Down Expand Up @@ -102,4 +107,9 @@ QRectF getFocusSurface(const DisplayGroup& group)
group.width() - leftMargin - rightMargin,
group.height() - topMargin - bottomMargin};
}

qreal getMinWindowSize()
{
return minWindowSize;
}
}
9 changes: 9 additions & 0 deletions tide/core/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
*/
namespace ui
{
/** @name Fixed UI element sizes. */
//@{
/** @return the size of regular buttons. */
qreal getButtonSize();

Expand All @@ -65,9 +67,16 @@ QMarginsF getFocusedWindowControlsMargins(const Content& content);

/** @return the width of the fixed side control bar on the control surface. */
qreal getSideControlWidth();
//@}

/** @name Constraints for window layout. */
//@{
/** @return the surface of the DisplayGroup available for focused windows. */
QRectF getFocusSurface(const DisplayGroup& group);

/** @return the minimum size that a normal window should have. */
qreal getMinWindowSize();
//@}
}

#endif
Loading