Skip to content

Bug: A SpBoxLayout with a border gets extra width/height when adding presenters #1818

@koendehondt

Description

@koendehondt

Step 1

Consider this code:

	application := SpApplication new
		addStyleSheetFromString: '.application [
			.tab [ Container { #borderWidth: 3, #borderColor: #FFFFFF } ] ]'.
	mainPresenter := SpPresenter newApplication: application.
	iconLayout := SpBoxLayout newLeftToRight
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			yourself.
	icon := (SpPresenter newApplication: application)
		layout: iconLayout;
		addStyle: 'tab';
		yourself.
	iconBar := (SpPresenter newApplication: application)
		layout: (SpBoxLayout newLeftToRight
			spacing: 10;
			add: icon expand: false;
			yourself);
		yourself.
	mainLayout := SpBoxLayout newTopToBottom
		vAlignCenter;
		hAlignCenter;
		yourself.
	mainLayout add: iconBar expand: false.
	mainPresenter layout: mainLayout; open.

It creates an iconBar presenter with a SpBoxLayout that holds 1 icon presenter. The latter holds an image. Theicon presenter has a white border of 3 pixels to show the issue clearly later on.

The code snippet opens this window:

Image

All good. The 3-pixel white border encloses the image as expected.

Step 2

Change the code to put 2 images in the iconLayout:

iconLayout := SpBoxLayout newLeftToRight
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			yourself.

and run the code again. Now this window opens:

Image

The white border is now wider than the space taken by the images. The extra space inside the border is 6 pixels.

Step 3

Change the code again, now to put 3 images in the iconLayout:

iconLayout := SpBoxLayout newLeftToRight
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			yourself.

and run the code again. Now this window opens:

Image

The white border is now wider again. It is 12 pixels wide.

Step 4

We can continue adding more images. The extra space inside the border grows 6 pixels with every icon we add to the layout.

The problem also exists for a vertical box layout. Here is the code (iconLayout := SpBoxLayout newTopToBottom is the only change):

application := SpApplication new
		addStyleSheetFromString: '.application [
			.tab [ Container { #borderWidth: 3, #borderColor: #FFFFFF } ] ]'.
	mainPresenter := SpPresenter newApplication: application.
	iconLayout := SpBoxLayout newTopToBottom
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			add: (mainPresenter newImage image: (mainPresenter iconNamed: 'box')) expand: false;
			yourself.
	icon := (SpPresenter newApplication: application)
		layout: iconLayout;
		addStyle: 'tab';
		yourself.
	iconBar := (SpPresenter newApplication: application)
		layout: (SpBoxLayout newLeftToRight
			spacing: 10;
			add: icon expand: false;
			yourself);
		yourself.
	mainLayout := SpBoxLayout newTopToBottom
		vAlignCenter;
		hAlignCenter;
		yourself.
	mainLayout add: iconBar expand: false.
	mainPresenter layout: mainLayout; open.

It opens this window:

Image

Bug 1

The extra space is added by SpMorphicBoxAdapter>>#verifyBoxExtentOf:withChild::

verifyBoxExtentOf: aPanel withChild: childMorph
	| width height newPanelWidth newPanelHeight |

	width := childMorph width + (widget borderWidth * 2).
	height := childMorph height + (widget borderWidth * 2).

	layout isVertical 
		ifTrue: [ height := height + aPanel height + aPanel cellInset ]
		ifFalse: [ width := width + aPanel width + aPanel cellInset ].

	newPanelWidth := aPanel hResizing = #rigid
		ifTrue: [ aPanel width ]
		ifFalse: [ aPanel width max: width ].
	newPanelHeight := aPanel vResizing = #rigid
		ifTrue: [ aPanel height ]
		ifFalse: [ aPanel height max: height ].
	aPanel extent: newPanelWidth @ newPanelHeight

As you can see in the two assignments at the top of the method body, every time a child morph is added, the width/height of the border on either side of the box is added to the width/height of the box, in addition to adding the width/height of the added child. That is the bug that results in the bad display we see in the windows.

Bug 2

Now consider the same code for opening the window, but without any images in the box layout (see iconLayout := SpBoxLayout newLeftToRight):

	application := SpApplication new
		addStyleSheetFromString: '.application [
			.tab [ Container { #borderWidth: 3, #borderColor: #FFFFFF } ] ]'.
	mainPresenter := SpPresenter newApplication: application.
	iconLayout := SpBoxLayout newLeftToRight.
	icon := (SpPresenter newApplication: application)
		layout: iconLayout;
		addStyle: 'tab';
		yourself.
	iconBar := (SpPresenter newApplication: application)
		layout: (SpBoxLayout newLeftToRight
			spacing: 10;
			add: icon expand: false;
			yourself);
		yourself.
	mainLayout := SpBoxLayout newTopToBottom
		vAlignCenter;
		hAlignCenter;
		yourself.
	mainLayout add: iconBar expand: false.
	mainPresenter layout: mainLayout; open.

Then we see this window:

Image

The border is not visible, indicating that the initial dimensions of the morph for the box layout are incorrect. The width and the height are zero, while the initial width/height of the morph should be twice the width/height of the border.

Bug 3

There is a third bug. SpMorphicBoxAdapter>>#verifyBoxExtentOf:withChild: does not apply the spacing of the SpBoxLayout correctly. I will report that bug in a separate issue ticket.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions