435 lines
9 KiB
Text
435 lines
9 KiB
Text
' Gambas class file
|
|
|
|
Export
|
|
Inherits UserContainer
|
|
|
|
Property Layout, Settings As Integer[]
|
|
Property Border As Boolean
|
|
|
|
Event Resize
|
|
|
|
Private Const MIN_SIZE As Integer = 8
|
|
|
|
Private $hObs As Observer
|
|
Private $hObsPanel As Observer
|
|
Private $cWeight As New Collection
|
|
Private $bLayouting As Boolean
|
|
Private $hPanel As Panel
|
|
Private $aResize As New DrawingArea[]
|
|
|
|
Private $XMin As Integer
|
|
Private $XMax As Integer
|
|
Private $iNoArrange As Integer
|
|
Private $bVertical As Boolean
|
|
Private $bBorder As Boolean = True
|
|
|
|
Public Sub _new()
|
|
|
|
$bVertical = Me Is VSplit
|
|
$hPanel = New Panel(Me)
|
|
'$hPanel.Border = Border.Plain
|
|
Me._Container = $hPanel
|
|
$hObs = New Observer(Me) As "Container"
|
|
$hObsPanel = New Observer($hPanel) As "Container"
|
|
|
|
End
|
|
|
|
Private Sub GetChildren(Optional bHidden As Boolean) As Control[]
|
|
|
|
Dim aControl As New Control[]
|
|
Dim hChild As Control
|
|
|
|
For Each hChild In $hPanel.Children
|
|
If Not bHidden And If Not hChild.Visible Then Continue
|
|
aControl.Add(hChild)
|
|
Next
|
|
|
|
Return aControl
|
|
|
|
End
|
|
|
|
|
|
' Private Sub GetTotalWeight() As Integer
|
|
'
|
|
' Dim hChild As Control
|
|
' Dim iWeight As Integer
|
|
'
|
|
' For Each hChild In GetChildren()
|
|
' Try iWeight += $cWeight[Object.Address(hChild)]
|
|
' Next
|
|
'
|
|
' Return iWeight
|
|
'
|
|
' End
|
|
|
|
Public Sub Container_Arrange()
|
|
|
|
Dim cNewWeight As Collection
|
|
Dim hChild As Control
|
|
Dim fWeight As Float
|
|
Dim fNewWeight As Float
|
|
Dim fTotalWeight As Float
|
|
Dim I As Integer
|
|
Dim aAllChildren As Control[]
|
|
Dim aChildren As Control[]
|
|
|
|
If $iNoArrange Or If $bLayouting Then Return
|
|
|
|
Inc $iNoArrange
|
|
|
|
'Debug Me.W;; Me.H
|
|
$hPanel.Move(0, 0, Me.W, Me.H)
|
|
|
|
aChildren = GetChildren()
|
|
aAllChildren = GetChildren(True)
|
|
|
|
If aChildren.Count = 0 Then
|
|
|
|
For I = 0 To $aResize.Max
|
|
$aResize[I].Delete
|
|
Next
|
|
$aResize.Clear
|
|
$cWeight.Clear
|
|
|
|
Else
|
|
|
|
'If $cWeight.Count <> aChildren.Count Then
|
|
|
|
fNewWeight = 1 / aChildren.Count
|
|
|
|
cNewWeight = New Collection
|
|
|
|
For Each hChild In aAllChildren
|
|
Try fWeight = $cWeight[Object.Address(hChild)]
|
|
If Error Then fWeight = fNewWeight
|
|
cNewWeight[Object.Address(hChild)] = fWeight
|
|
If hChild.Visible Then fTotalWeight += fWeight
|
|
Next
|
|
|
|
' If fTotalWeight <> 1 Then
|
|
' For Each hChild In aChildren
|
|
' cNewWeight[Object.Address(hChild)] /= fTotalWeight
|
|
' Next
|
|
' Endif
|
|
'
|
|
|
|
$cWeight = cNewWeight
|
|
|
|
'Endif
|
|
|
|
If $aResize.Count > (aChildren.Count - 1) Then
|
|
For I = aChildren.Count - 1 To $aResize.Max
|
|
$aResize[I].Delete
|
|
Next
|
|
$aResize.Resize(aChildren.Count - 1)
|
|
Else If $aResize.Count < (aChildren.Count - 1) Then
|
|
$aResize.Resize(aChildren.Count - 1)
|
|
Me._Container = Null
|
|
For I = aChildren.Count - 2 DownTo 0
|
|
If $aResize[I] Then Break
|
|
$aResize[I] = New DrawingArea(Me) As "Resize"
|
|
With $aResize[I]
|
|
.NoBackground = True
|
|
.Raise
|
|
'.Background = Color.Yellow
|
|
.Mouse = If($bVertical, Mouse.SplitV, Mouse.SplitH)
|
|
.Tag = I
|
|
End With
|
|
Next
|
|
Me._Container = $hPanel
|
|
Endif
|
|
|
|
Endif
|
|
|
|
DoLayout
|
|
|
|
Dec $iNoArrange
|
|
|
|
End
|
|
|
|
Private Sub GetSepWidth() As Integer
|
|
|
|
Return If(Me.Spacing, Desktop.Scale, 1)
|
|
|
|
End
|
|
|
|
Private Function Layout_Read() As Integer[]
|
|
|
|
Dim aLayout As New Integer[]
|
|
Dim WTotal As Integer = If($bVertical, Me.H, Me.W)
|
|
Dim hChild As Control
|
|
Dim W As Integer
|
|
Dim SW As Integer = GetSepWidth()
|
|
|
|
'For Each fWeight In $cWeight
|
|
' fTotal += fWeight
|
|
'Next
|
|
|
|
For Each hChild In $hPanel.Children
|
|
If Not hChild.Visible Then
|
|
aLayout.Add(0)
|
|
Else
|
|
'Try fWeight = $cWeight[Object.Address(hChild)]
|
|
'If Error Then
|
|
If $bVertical Then
|
|
W = hChild.H
|
|
If (hChild.Y + W) < WTotal Then W += SW
|
|
Else
|
|
W = hChild.W
|
|
If (hChild.X + W) < WTotal Then W += SW
|
|
Endif
|
|
aLayout.Add(W)
|
|
'Else
|
|
' aLayout.Add(Max(1, CInt(WTotal * fWeight / fTotal + 0.5)))
|
|
'Endif
|
|
Endif
|
|
Next
|
|
|
|
'Debug String[](aLayout).Join(",");; "("; WTotal; ")"
|
|
|
|
Return aLayout
|
|
|
|
End
|
|
|
|
Private Sub DoLayout()
|
|
|
|
Dim I, W, WMax, WTotal As Integer
|
|
Dim hChild As Control
|
|
Dim X As Integer
|
|
Dim aChildren As Control[]
|
|
Dim fTotalWeight As Float
|
|
Dim SW As Integer
|
|
|
|
If $bLayouting Then Return
|
|
|
|
SW = GetSepWidth()
|
|
|
|
$bLayouting = True
|
|
|
|
For Each hChild In GetChildren()
|
|
Try fTotalWeight += $cWeight[Object.Address(hChild)]
|
|
Next
|
|
|
|
aChildren = GetChildren(True)
|
|
|
|
WMax = If($bVertical, Me.H, Me.W)
|
|
|
|
For I = 0 To aChildren.Max
|
|
|
|
hChild = aChildren[I]
|
|
If Not hChild.Visible Then Continue
|
|
|
|
W = Max(MIN_SIZE, CInt($cWeight[Object.Address(hChild)] * WMax / fTotalWeight + 0.5))
|
|
WTotal += W
|
|
|
|
If $bVertical Then
|
|
aChildren[I].Height = W - SW
|
|
Else
|
|
aChildren[I].Width = W - SW
|
|
Endif
|
|
|
|
Next
|
|
|
|
aChildren = GetChildren()
|
|
|
|
If aChildren.Count Then
|
|
|
|
If $bVertical Then
|
|
|
|
For Each hChild In aChildren
|
|
hChild.Move(0, X, Me.W, hChild.H)
|
|
X += hChild.H + SW
|
|
Next
|
|
|
|
hChild.Height = WMax - hChild.Y
|
|
|
|
For I = 0 To $aResize.Max
|
|
hChild = aChildren[I + 1]
|
|
If Not hChild.Visible Then Continue
|
|
$aResize[I].Move(0, hChild.Y - Desktop.Scale \ 2 - SW \ 2, Me.W, Desktop.Scale)
|
|
Next
|
|
|
|
Else
|
|
|
|
If System.RightToLeft Then
|
|
|
|
X = WMax
|
|
|
|
For Each hChild In aChildren
|
|
X -= hChild.W
|
|
hChild.Move(X, 0, hChild.W, Me.H)
|
|
X -= SW
|
|
Next
|
|
|
|
hChild.Width += hChild.X
|
|
hChild.X = 0
|
|
|
|
For I = 0 To $aResize.Max
|
|
hChild = aChildren[I]
|
|
$aResize[I].Move(hChild.X - Desktop.Scale \ 2 - SW \ 2, 0, Desktop.Scale, Me.H)
|
|
Next
|
|
|
|
Else
|
|
|
|
For Each hChild In aChildren
|
|
hChild.Move(X, 0, hChild.W, Me.H)
|
|
X += hChild.W + SW
|
|
Next
|
|
|
|
hChild.Width = WMax - hChild.X
|
|
|
|
For I = 0 To $aResize.Max
|
|
hChild = aChildren[I + 1]
|
|
$aResize[I].Move(hChild.X - Desktop.Scale \ 2 - SW \ 2, 0, Desktop.Scale, Me.H)
|
|
Next
|
|
|
|
Endif
|
|
|
|
Endif
|
|
|
|
Endif
|
|
|
|
$bLayouting = False
|
|
|
|
End
|
|
|
|
Private Sub Layout_Write(Value As Integer[])
|
|
|
|
Dim I As Integer
|
|
Dim iTotal As Integer
|
|
Dim hChild As Control
|
|
|
|
'Debug String[](Value).Join(",")
|
|
|
|
' Value = Value.Copy()
|
|
' iTotal = NormalizeLayout(Value)
|
|
|
|
For I = 0 To Value.Max
|
|
If Value[I] > 0 Then iTotal += Value[I]
|
|
Next
|
|
|
|
$cWeight = New Collection
|
|
For I = 0 To $hPanel.Children.Count - 1
|
|
hChild = $hPanel.Children[I]
|
|
If I <= Value.Max And If Value[I] > 0 Then
|
|
$cWeight[Object.Address(hChild)] = Value[I] / iTotal
|
|
hChild.Show
|
|
Else
|
|
hChild.Hide
|
|
Endif
|
|
Next
|
|
|
|
DoLayout
|
|
|
|
End
|
|
|
|
Public Sub Resize_MouseDown()
|
|
|
|
Dim aChildren As Control[] = GetChildren()
|
|
Dim I As Integer = Last.Tag
|
|
Dim SW As Integer = GetSepWidth()
|
|
|
|
If $bVertical Then
|
|
$XMin = aChildren[I].ScreenY
|
|
$XMax = aChildren[I + 1].ScreenY + aChildren[I + 1].H + SW
|
|
Else
|
|
If System.RightToLeft Then
|
|
$XMin = aChildren[I + 1].ScreenX
|
|
$XMax = aChildren[I].ScreenX + aChildren[I].W + SW
|
|
Else
|
|
$XMin = aChildren[I].ScreenX
|
|
$XMax = aChildren[I + 1].ScreenX + aChildren[I + 1].W + SW
|
|
Endif
|
|
Endif
|
|
|
|
End
|
|
|
|
Public Sub Resize_MouseMove()
|
|
|
|
Dim aChildren As Control[] = GetChildren()
|
|
Dim hResize As DrawingArea = Last
|
|
Dim I As Integer = hResize.Tag
|
|
Dim I2 As Integer
|
|
Dim X As Integer
|
|
Dim SW As Integer = GetSepWidth()
|
|
|
|
If Not Mouse.Left Then Return
|
|
|
|
Inc $iNoArrange
|
|
|
|
If $bVertical Then
|
|
|
|
X = Min(Max(Mouse.ScreenY, $XMin + MIN_SIZE), $XMax - MIN_SIZE)
|
|
|
|
aChildren[I].H = X - $XMin - SW
|
|
aChildren[I + 1].Move(0, X - Me.ScreenY, Me.W, $XMax - X - SW)
|
|
|
|
hResize.Move(0, aChildren[I + 1].Y - Desktop.Scale \ 2 - SW \ 2, Me.W, Desktop.Scale)
|
|
|
|
' For Each hChild In aChildren
|
|
' W = hChild.H
|
|
' If hChild <> aChildren[aChildren.Max] Then Inc W
|
|
' $cWeight[Object.Address(hChild)] = W
|
|
' Next
|
|
|
|
Else
|
|
|
|
X = Min(Max(Mouse.ScreenX, $XMin + MIN_SIZE), $XMax - MIN_SIZE)
|
|
|
|
If System.RightToLeft Then
|
|
I2 = I
|
|
I = I2 + 1
|
|
Else
|
|
I2 = I + 1
|
|
Endif
|
|
|
|
aChildren[I].W = X - $XMin - SW
|
|
aChildren[I2].Move(X - Me.ScreenX, 0, $XMax - X - SW, Me.H)
|
|
|
|
hResize.Move(aChildren[I2].X - Desktop.Scale \ 2 - SW \ 2, 0, Desktop.Scale, Me.H)
|
|
|
|
Endif
|
|
|
|
Dec $iNoArrange
|
|
|
|
Raise Resize
|
|
|
|
End
|
|
|
|
Public Sub Resize_MouseUp()
|
|
|
|
$cWeight.Clear
|
|
Layout_Write(Layout_Read())
|
|
|
|
End
|
|
|
|
Public Sub Resize_Draw()
|
|
|
|
Dim X As Integer
|
|
|
|
If Not $bBorder Then Return
|
|
|
|
X = Desktop.Scale \ 2 - 1
|
|
|
|
Draw.Foreground = Color.LightForeground
|
|
If $bVertical Then
|
|
Draw.Line(0, X, Me.W - 1, X)
|
|
Else
|
|
Draw.Line(X, 0, X, Me.H - 1)
|
|
Endif
|
|
|
|
End
|
|
|
|
Private Function Border_Read() As Boolean
|
|
|
|
Return $bBorder
|
|
|
|
End
|
|
|
|
Private Sub Border_Write(Value As Boolean)
|
|
|
|
If $bBorder = Value Then Return
|
|
$bBorder = Value
|
|
DoLayout
|
|
|
|
End
|