added 6 changesets to branch 'refs/remotes/HaikuPM-github/package-management' old head: 38c62dfb8b5acffe9373b19e087d037d38a281a5 new head: b53a2e6af53a5f375e63a50c4a021bb8967cb2d7 overview: https://github.com/haiku/HaikuPM/compare/38c62df...b53a2e6 ---------------------------------------------------------------------------- 406ad5b: BString::SetToFormat(): Add printf format function attribute b1c3379: _user_debug_output(): Fix for long strings The wrong length was passed to debug_puts(). 4a8da96: BLayoutUtils: Add GetLayoutTreeDump() Returns a debug output string listing the basic layout properties of the view/item hierarchy. 5c56812: BControlLook::ComposeSpacing(): Avoid non-integers 88f12ad: Add private BViewPort class * It simplifies putting regular layout-aware views or layout items into a BScrollView. * Not quite complete yet: Height-for-width support is missing, but that also requires fixing BScrollView in this respect. Scroll bar auto-hide support would be nice as well. b53a2e6: package daemon: ProblemWindow: Use a scroll view [ Ingo Weinhold <ingo_weinhold@xxxxxx> ] ---------------------------------------------------------------------------- 10 files changed, 521 insertions(+), 13 deletions(-) headers/os/interface/LayoutUtils.h | 18 +- headers/os/support/String.h | 3 +- headers/private/interface/ViewPort.h | 53 ++++++ src/kits/interface/ControlLook.cpp | 6 +- src/kits/interface/Jamfile | 1 + src/kits/interface/LayoutUtils.cpp | 115 ++++++++++- src/kits/interface/ViewPort.cpp | 306 ++++++++++++++++++++++++++++++ src/servers/package/Jamfile | 2 +- src/servers/package/ProblemWindow.cpp | 22 ++- src/system/kernel/debug/debug.cpp | 8 +- ############################################################################ Commit: 406ad5becebc1761f0858fbd0af64f0be8870ec0 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:43:05 2013 UTC BString::SetToFormat(): Add printf format function attribute ---------------------------------------------------------------------------- diff --git a/headers/os/support/String.h b/headers/os/support/String.h index 4ce0d13..e33fbc0 100644 --- a/headers/os/support/String.h +++ b/headers/os/support/String.h @@ -55,7 +55,8 @@ public: BString& SetToChars(const BString& string, int32 charCount); BString& AdoptChars(BString& from, int32 charCount); - BString& SetToFormat(const char* format, ...); + BString& SetToFormat(const char* format, ...) + __attribute__((__format__(__printf__, 2, 3))); BString& SetToFormatVarArgs(const char* format, va_list args); ############################################################################ Commit: b1c3379c7e17a5368f3ce6642e3e995143779481 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:43:47 2013 UTC _user_debug_output(): Fix for long strings The wrong length was passed to debug_puts(). ---------------------------------------------------------------------------- diff --git a/src/system/kernel/debug/debug.cpp b/src/system/kernel/debug/debug.cpp index caa90d1..15adaba 100644 --- a/src/system/kernel/debug/debug.cpp +++ b/src/system/kernel/debug/debug.cpp @@ -2268,13 +2268,15 @@ _user_debug_output(const char* userString) char string[512]; int32 length; + int32 toWrite; do { length = user_strlcpy(string, userString, sizeof(string)); if (length <= 0) break; - debug_puts(string, length); - userString += sizeof(string) - 1; - } while (length >= (ssize_t)sizeof(string)); + toWrite = std::min(length, (int32)sizeof(string) - 1); + debug_puts(string, toWrite); + userString += toWrite; + } while (length > toWrite); } ############################################################################ Commit: 4a8da96088a5aa35d7377c97746f6151ff0e6457 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:46:36 2013 UTC BLayoutUtils: Add GetLayoutTreeDump() Returns a debug output string listing the basic layout properties of the view/item hierarchy. ---------------------------------------------------------------------------- diff --git a/headers/os/interface/LayoutUtils.h b/headers/os/interface/LayoutUtils.h index cac5c2e..24e91c0 100644 --- a/headers/os/interface/LayoutUtils.h +++ b/headers/os/interface/LayoutUtils.h @@ -1,16 +1,21 @@ /* - * Copyright 2006, Haiku, Inc. All rights reserved. + * Copyright 2006-2013, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _LAYOUT_UTILS_H #define _LAYOUT_UTILS_H + #include <Alignment.h> #include <Rect.h> #include <Size.h> +#include <String.h> + +class BLayoutItem; class BView; + class BLayoutUtils { public: // static float AddSizesFloat(float a, float b); @@ -36,6 +41,17 @@ public: BAlignment alignment); static void AlignInFrame(BView* view, BRect frame); static BRect MoveIntoFrame(BRect rect, BSize frameSize); + + // debugging + static BString GetLayoutTreeDump(BView* view); + static BString GetLayoutTreeDump(BLayoutItem* item); + +private: + static void _GetLayoutTreeDump(BView* view, int level, + BString& _output); + static void _GetLayoutTreeDump(BLayoutItem* item, + int level, bool isViewLayout, + BString& _output); }; #endif // _LAYOUT_UTILS_H diff --git a/src/kits/interface/LayoutUtils.cpp b/src/kits/interface/LayoutUtils.cpp index 577da47..67e2bcc 100644 --- a/src/kits/interface/LayoutUtils.cpp +++ b/src/kits/interface/LayoutUtils.cpp @@ -1,12 +1,17 @@ /* - * Copyright 2006-2010, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Copyright 2006-2013, Ingo Weinhold, ingo_weinhold@xxxxxx. * Distributed under the terms of the MIT License. */ #include <LayoutUtils.h> +#include <typeinfo> + +#include <Layout.h> #include <View.h> +#include "ViewLayoutItem.h" + // // AddSizesFloat // float @@ -230,3 +235,111 @@ BLayoutUtils::MoveIntoFrame(BRect rect, BSize frameSize) return rect.OffsetToSelf(leftTop); } + + +/*static*/ BString +BLayoutUtils::GetLayoutTreeDump(BView* view) +{ + BString result; + _GetLayoutTreeDump(view, 0, result); + return result; +} + + +/*static*/ BString +BLayoutUtils::GetLayoutTreeDump(BLayoutItem* item) +{ + BString result; + _GetLayoutTreeDump(item, 0, false, result); + return result; +} + + +/*static*/ void +BLayoutUtils::_GetLayoutTreeDump(BView* view, int level, BString& _output) +{ + BString indent; + indent.SetTo(' ', level * 2); + + if (view == NULL) { + _output << indent << "<null view>\n"; + return; + } + + BRect frame = view->Frame(); + BSize min = view->MinSize(); + BSize max = view->MinSize(); + BSize preferred = view->PreferredSize(); + _output << BString().SetToFormat( + "%sview %p (%s):\n" + "%s frame: (%f, %f, %f, %f)\n" + "%s min: (%f, %f)\n" + "%s max: (%f, %f)\n" + "%s pref: (%f, %f)\n", + indent.String(), view, typeid(*view).name(), + indent.String(), frame.left, frame.top, frame.right, frame.bottom, + indent.String(), min.width, min.height, + indent.String(), max.width, max.height, + indent.String(), preferred.width, preferred.height); + + if (BLayout* layout = view->GetLayout()) { + _GetLayoutTreeDump(layout, level, true, _output); + return; + } + + int32 count = view->CountChildren(); + for (int32 i = 0; i < count; i++) { + _output << indent << " ---\n"; + _GetLayoutTreeDump(view->ChildAt(i), level + 1, _output); + } +} + + +/*static*/ void +BLayoutUtils::_GetLayoutTreeDump(BLayoutItem* item, int level, + bool isViewLayout, BString& _output) +{ + if (BViewLayoutItem* viewItem = dynamic_cast<BViewLayoutItem*>(item)) { + _GetLayoutTreeDump(viewItem->View(), level, _output); + return; + } + + BString indent; + indent.SetTo(' ', level * 2); + + if (item == NULL) { + _output << indent << "<null item>\n"; + return; + } + + BLayout* layout = dynamic_cast<BLayout*>(item); + BRect frame = item->Frame(); + BSize min = item->MinSize(); + BSize max = item->MinSize(); + BSize preferred = item->PreferredSize(); + if (isViewLayout) { + _output << indent << BString().SetToFormat(" [layout %p (%s)]\n", + layout, typeid(*layout).name()); + } else { + _output << indent << BString().SetToFormat("item %p (%s):\n", + item, typeid(*item).name()); + } + _output << BString().SetToFormat( + "%s frame: (%f, %f, %f, %f)\n" + "%s min: (%f, %f)\n" + "%s max: (%f, %f)\n" + "%s pref: (%f, %f)\n", + indent.String(), frame.left, frame.top, frame.right, frame.bottom, + indent.String(), min.width, min.height, + indent.String(), max.width, max.height, + indent.String(), preferred.width, preferred.height); + + if (layout == NULL) + return; + + int32 count = layout->CountItems(); + for (int32 i = 0; i < count; i++) { + _output << indent << " ---\n"; + _GetLayoutTreeDump(layout->ItemAt(i), level + 1, false, _output); + } +} ############################################################################ Commit: 5c56812d900c7777c62eab899c0bb553459ef67b Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:47:28 2013 UTC BControlLook::ComposeSpacing(): Avoid non-integers ---------------------------------------------------------------------------- diff --git a/src/kits/interface/ControlLook.cpp b/src/kits/interface/ControlLook.cpp index acb95ed..bd44d4f 100644 --- a/src/kits/interface/ControlLook.cpp +++ b/src/kits/interface/ControlLook.cpp @@ -67,13 +67,13 @@ BControlLook::ComposeSpacing(float spacing) if (spacing == B_USE_DEFAULT_SPACING || spacing == B_USE_ITEM_SPACING) { return be_control_look->DefaultItemSpacing(); } else if (spacing == B_USE_HALF_ITEM_SPACING) { - return be_control_look->DefaultItemSpacing() * 0.5f; + return ceilf(be_control_look->DefaultItemSpacing() * 0.5f); } else if (spacing == B_USE_WINDOW_INSETS) { return be_control_look->DefaultItemSpacing(); } else if (spacing == B_USE_SMALL_SPACING) { - return be_control_look->DefaultItemSpacing() * 0.7f; + return ceilf(be_control_look->DefaultItemSpacing() * 0.7f); } else if (spacing == B_USE_BIG_SPACING) { - return be_control_look->DefaultItemSpacing() * 1.3f; + return ceilf(be_control_look->DefaultItemSpacing() * 1.3f); } return spacing; } ############################################################################ Commit: 88f12ad84fa46739ba94376b5324cdc35bd50b9c Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:51:03 2013 UTC Add private BViewPort class * It simplifies putting regular layout-aware views or layout items into a BScrollView. * Not quite complete yet: Height-for-width support is missing, but that also requires fixing BScrollView in this respect. Scroll bar auto-hide support would be nice as well. ---------------------------------------------------------------------------- diff --git a/headers/private/interface/ViewPort.h b/headers/private/interface/ViewPort.h new file mode 100644 index 0000000..cee7afb --- /dev/null +++ b/headers/private/interface/ViewPort.h @@ -0,0 +1,53 @@ +/* + * Copyright 2013, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Ingo Weinhold <ingo_weinhold@xxxxxx> + */ +#ifndef _VIEW_PORT_H +#define _VIEW_PORT_H + + +#include <View.h> + + +namespace BPrivate { + + +class BViewPort : public BView { +public: + BViewPort(BView* child = NULL); + BViewPort(BLayoutItem* child); + BViewPort(const char* name, + BView* child = NULL); + BViewPort(const char* name, + BLayoutItem* child); + virtual ~BViewPort(); + + BView* ChildView() const; + void SetChildView(BView* child); + + BLayoutItem* ChildItem() const; + void SetChildItem(BLayoutItem* child); + +private: + class ViewPortLayout; + friend class ViewPortLayout; + +private: + void _Init(); + +private: + ViewPortLayout* fLayout; + BLayoutItem* fChild; +}; + + +} // namespace BPrivate + + +using ::BPrivate::BViewPort; + + +#endif // _VIEW_PORT_H diff --git a/src/kits/interface/Jamfile b/src/kits/interface/Jamfile index 5fe6215..ad31fd2 100644 --- a/src/kits/interface/Jamfile +++ b/src/kits/interface/Jamfile @@ -129,6 +129,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { TwoDimensionalLayout.cpp View.cpp ViewLayoutItem.cpp + ViewPort.cpp Window.cpp WindowStack.cpp ZombieReplicantView.cpp diff --git a/src/kits/interface/ViewPort.cpp b/src/kits/interface/ViewPort.cpp new file mode 100644 index 0000000..c2ea225 --- /dev/null +++ b/src/kits/interface/ViewPort.cpp @@ -0,0 +1,306 @@ +/* + * Copyright 2013, Ingo Weinhold, ingo_weinhold@xxxxxx. + * Distributed under the terms of the MIT License. + */ + + +#include <ViewPort.h> + +#include <algorithm> + +#include <AbstractLayout.h> +#include <ScrollBar.h> + +#include "ViewLayoutItem.h" + + +namespace BPrivate { + + +// #pragma mark - ViewPortLayout + + +class BViewPort::ViewPortLayout : public BAbstractLayout { +public: + ViewPortLayout(BViewPort* viewPort) + : + BAbstractLayout(), + fViewPort(viewPort), + fHasViewChild(false), + fIsCacheValid(false), + fMin(), + fMax(), + fPreferred() + { + } + + BView* ChildView() const + { + if (!fHasViewChild) + return NULL; + if (BViewLayoutItem* item = dynamic_cast<BViewLayoutItem*>(ItemAt(0))) + return item->View(); + return NULL; + } + + void SetChildView(BView* view) + { + _UnsetChild(); + + if (view != NULL && AddView(0, view) != NULL) + fHasViewChild = true; + } + + BLayoutItem* ChildItem() const + { + return ItemAt(0); + } + + void SetChildItem(BLayoutItem* item) + { + _UnsetChild(); + + if (item != NULL) + AddItem(0, item); + } + + virtual BSize BaseMinSize() + { + _ValidateMinMax(); + return fMin; + } + + virtual BSize BaseMaxSize() + { + _ValidateMinMax(); + return fMax; + } + + virtual BSize BasePreferredSize() + { + _ValidateMinMax(); + return fPreferred; + } + + virtual BAlignment BaseAlignment() + { + return BAbstractLayout::BaseAlignment(); + } + + virtual bool HasHeightForWidth() + { + _ValidateMinMax(); + return false; + // TODO: Support height-for-width! + } + + virtual void GetHeightForWidth(float width, float* min, float* max, + float* preferred) + { + if (!HasHeightForWidth()) + return; + + // TODO: Support height-for-width! + } + + virtual void LayoutInvalidated(bool children) + { + fIsCacheValid = false; + } + + virtual void DoLayout() + { + _ValidateMinMax(); + + BLayoutItem* child = ItemAt(0); + if (child == NULL) + return; + + // Determine the layout area: LayoutArea() will only give us the size + // of the view port's frame. + BSize viewSize = LayoutArea().Size(); + BSize layoutSize = viewSize; + + BSize childMin = child->MinSize(); + BSize childMax = child->MaxSize(); + + // apply the maximum constraints + layoutSize.width = std::min(layoutSize.width, childMax.width); + layoutSize.height = std::min(layoutSize.height, childMax.height); + + // apply the minimum constraints + layoutSize.width = std::max(layoutSize.width, childMin.width); + layoutSize.height = std::max(layoutSize.height, childMin.height); + + // TODO: Support height-for-width! + + child->AlignInFrame(BRect(BPoint(0, 0), layoutSize)); + + _UpdateScrollBar(fViewPort->ScrollBar(B_HORIZONTAL), viewSize.width, + layoutSize.width); + _UpdateScrollBar(fViewPort->ScrollBar(B_VERTICAL), viewSize.height, + layoutSize.height); + } + +private: + void _UnsetChild() + { + if (CountItems() > 0) { + BLayoutItem* item = RemoveItem((int32)0); + if (fHasViewChild) + delete item; + fHasViewChild = false; + } + } + + void _ValidateMinMax() + { + if (fIsCacheValid) + return; + + if (BLayoutItem* child = ItemAt(0)) { + fMin = child->MinSize(); + if (_IsHorizontallyScrollable()) + fMin.width = -1; + if (_IsVerticallyScrollable()) + fMin.height = -1; + fMax = child->MaxSize(); + fPreferred = child->PreferredSize(); + // TODO: Support height-for-width! + } else { + fMin.Set(-1, -1); + fMax.Set(B_SIZE_UNLIMITED, B_SIZE_UNLIMITED); + fPreferred.Set(20, 20); + } + + fIsCacheValid = true; + } + + bool _IsHorizontallyScrollable() const + { + return fViewPort->ScrollBar(B_HORIZONTAL) != NULL; + } + + bool _IsVerticallyScrollable() const + { + return fViewPort->ScrollBar(B_VERTICAL) != NULL; + } + + void _UpdateScrollBar(BScrollBar* scrollBar, float viewPortSize, + float dataSize) + { + if (scrollBar == NULL) + return; + + if (viewPortSize < dataSize) { + scrollBar->SetRange(0, dataSize - viewPortSize); + scrollBar->SetProportion(viewPortSize / dataSize); + float smallStep; + scrollBar->GetSteps(&smallStep, NULL); + scrollBar->SetSteps(smallStep, viewPortSize); + } else { + scrollBar->SetRange(0, 0); + scrollBar->SetProportion(1); + } + } + +private: + BViewPort* fViewPort; + bool fHasViewChild; + bool fIsCacheValid; + BSize fMin; + BSize fMax; + BSize fPreferred; +}; + + +// #pragma mark - BViewPort + + +BViewPort::BViewPort(BView* child) + : + BView(NULL, 0), + fChild(NULL) +{ + _Init(); + SetChildView(child); +} + + +BViewPort::BViewPort(BLayoutItem* child) + : + BView(NULL, 0), + fChild(NULL) +{ + _Init(); + SetChildItem(child); +} + + +BViewPort::BViewPort(const char* name, BView* child) + : + BView(name, 0), + fChild(NULL) +{ + _Init(); + SetChildView(child); +} + + +BViewPort::BViewPort(const char* name, BLayoutItem* child) + : + BView(name, 0), + fChild(NULL) +{ + _Init(); + SetChildItem(child); +} + + +BViewPort::~BViewPort() +{ +} + + +BView* +BViewPort::ChildView() const +{ + return fLayout->ChildView(); +} + + +void +BViewPort::SetChildView(BView* child) +{ + fLayout->SetChildView(child); + InvalidateLayout(); +} + + +BLayoutItem* +BViewPort::ChildItem() const +{ + return fLayout->ChildItem(); +} + + +void +BViewPort::SetChildItem(BLayoutItem* child) +{ + fLayout->SetChildItem(child); + InvalidateLayout(); +} + + +void +BViewPort::_Init() +{ + fLayout = new ViewPortLayout(this); + SetLayout(fLayout); +} + + +} // namespace BPrivate + + +using ::BPrivate::BViewPort; ############################################################################ Commit: b53a2e6af53a5f375e63a50c4a021bb8967cb2d7 Author: Ingo Weinhold <ingo_weinhold@xxxxxx> Date: Wed Sep 11 02:53:06 2013 UTC package daemon: ProblemWindow: Use a scroll view ---------------------------------------------------------------------------- diff --git a/src/servers/package/Jamfile b/src/servers/package/Jamfile index 348dc1b..d2859db 100644 --- a/src/servers/package/Jamfile +++ b/src/servers/package/Jamfile @@ -1,7 +1,7 @@ SubDir HAIKU_TOP src servers package ; UsePrivateSystemHeaders ; -UsePrivateHeaders app kernel shared ; +UsePrivateHeaders app interface kernel shared ; Server package_daemon : diff --git a/src/servers/package/ProblemWindow.cpp b/src/servers/package/ProblemWindow.cpp index db0493a..8dc68de 100644 --- a/src/servers/package/ProblemWindow.cpp +++ b/src/servers/package/ProblemWindow.cpp @@ -10,6 +10,7 @@ #include <GroupView.h> #include <LayoutBuilder.h> #include <RadioButton.h> +#include <ScrollView.h> #include <StringView.h> #include <package/solver/Solver.h> #include <package/solver/SolverPackage.h> @@ -18,6 +19,7 @@ #include <AutoLocker.h> #include <package/manager/Exceptions.h> +#include <ViewPort.h> using namespace BPackageKit; @@ -70,19 +72,33 @@ ProblemWindow::ProblemWindow() if (fDoneSemaphore < 0) throw std::bad_alloc(); + BStringView* topTextView = NULL; + BViewPort* viewPort = NULL; + BLayoutBuilder::Group<>(this, B_VERTICAL, B_USE_DEFAULT_SPACING) .SetInsets(B_USE_SMALL_INSETS) - .Add(new BStringView(NULL, + .Add(topTextView = new BStringView(NULL, "The following problems have been encountered. Please select a " "solution for each:")) -// TODO: Use a scroll view! - .Add(fContainerView = new BGroupView(B_VERTICAL, 0)) + .Add(new BScrollView(NULL, viewPort = new BViewPort(), 0, false, true)) .AddGroup(B_HORIZONTAL) .Add(fCancelButton = new BButton("Cancel", new BMessage(B_CANCEL))) .AddGlue() .Add(fRetryButton = new BButton("Retry", new BMessage(kRetryMessage))) .End(); + + topTextView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + viewPort->SetChildView(fContainerView = new BGroupView(B_VERTICAL, 0)); + + // set small scroll step (large step will be set by the view port) + BFont font; + topTextView->GetFont(&font); + font_height fontHeight; + font.GetHeight(&fontHeight); + float smallStep = ceilf(fontHeight.ascent + fontHeight.descent); + viewPort->ScrollBar(B_VERTICAL)->SetSteps(smallStep, smallStep); }