Need some help with Label Painting...

ALX

Well-known member
Joined
Nov 16, 2005
Messages
253
Location
Columbia, SC
Programming Experience
10+
I've cut this down to just the basics. This simple routine should (in my opinion) paint all the labels on the form a solid blue color.... but it does not.
Can somebody please tell me what I'm doing wrong here ?
VB.NET:
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE][SIZE=2] Form1
[/SIZE][SIZE=2][COLOR=#0000ff]Inherits[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.Form[/SIZE]
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] BBrush = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] SolidBrush(System.Drawing.Color.Blue)
[/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2] LabelList [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] ArrayList
[/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2] Q [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int16 = 55
 
#[/SIZE][SIZE=2][COLOR=#0000ff]Region[/COLOR][/SIZE][SIZE=2] " Windows Form Designer generated code "
[/SIZE]
[SIZE=2][COLOR=#0000ff]Public[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2]()
[/SIZE][SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].New()
[/SIZE][SIZE=2]InitializeComponent()
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Protected[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Overloads[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Overrides[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Dispose([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] disposing [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Boolean[/COLOR][/SIZE][SIZE=2])
[/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2] disposing [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]  If[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Not[/COLOR][/SIZE][SIZE=2] (components [/SIZE][SIZE=2][COLOR=#0000ff]Is[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Nothing[/COLOR][/SIZE][SIZE=2]) [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]      components.Dispose()
[/SIZE][SIZE=2][COLOR=#0000ff]  End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].Dispose(disposing)
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2] components [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.ComponentModel.IContainer
[/SIZE][SIZE=2][COLOR=#008000]
[/COLOR][/SIZE][SIZE=2]<System.Diagnostics.DebuggerStepThrough()> [/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] InitializeComponent()
[/SIZE][SIZE=2][COLOR=#008000]'
[/COLOR][/SIZE][SIZE=2][COLOR=#008000]'Form1
[/COLOR][/SIZE][SIZE=2][COLOR=#008000]'
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].AutoScaleBaseSize = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Drawing.Size(5, 13)
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].ClientSize = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Drawing.Size(992, 693)
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].Name = "Form1"
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].Text = "Form1"
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].WindowState = System.Windows.Forms.FormWindowState.Maximized
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
[/COLOR][/SIZE][SIZE=2]#[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Region[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] Form1_Load([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] e [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]MyBase[/COLOR][/SIZE][SIZE=2].Load
SetUpLabels()
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] SetUpLabels()
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] i [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int64
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] LabelN [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Label
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] x [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int16
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] y [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Int16[/SIZE]
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2] i = [/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].LabelList.Count - 1 [/SIZE][SIZE=2][COLOR=#0000ff]To[/COLOR][/SIZE][SIZE=2] 0 [/SIZE][SIZE=2][COLOR=#0000ff]Step[/COLOR][/SIZE][SIZE=2] -1
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].LabelList(i).Dispose()
[/SIZE][SIZE=2][COLOR=#0000ff]Next
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].LabelList.Clear()[/SIZE]
[SIZE=2]
[/SIZE][SIZE=2][COLOR=#0000ff]For[/COLOR][/SIZE][SIZE=2] i = 0 [/SIZE][SIZE=2][COLOR=#0000ff]To[/COLOR][/SIZE][SIZE=2] Q - 1 [/SIZE][SIZE=2][COLOR=#0000ff]Step[/COLOR][/SIZE][SIZE=2] 1
LabelN = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Windows.Forms.Label
LabelN.Name = i + 1.ToString
LabelN.BackColor = Color.Black
LabelN.ForeColor = Color.White
LabelN.Size = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Drawing.Size(168, 26)
LabelN.Font = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Drawing.Font("Microsoft Sans Serif", 14.25!, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, [/SIZE][SIZE=2][COLOR=#0000ff]CType[/COLOR][/SIZE][SIZE=2](0, [/SIZE][SIZE=2][COLOR=#0000ff]Byte[/COLOR][/SIZE][SIZE=2]))
[/SIZE]
[SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](LabelN.Name) = [/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](Q * 0.8) + 1 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]  x = 790
    y = 220
[/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](LabelN.Name) = [/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](Q * 0.6) + 1 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]  x = 606
    y = 220
[/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](LabelN.Name) = [/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](Q * 0.4) + 1 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]  x = 422
    y = 220
[/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](LabelN.Name) = [/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](Q * 0.2) + 1 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]  x = 238
    y = 220
[/SIZE][SIZE=2][COLOR=#0000ff]ElseIf[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]CInt[/COLOR][/SIZE][SIZE=2](LabelN.Name) = 1 [/SIZE][SIZE=2][COLOR=#0000ff]Then
[/COLOR][/SIZE][SIZE=2]  x = 54
    y = 220
[/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]If[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2]LabelN.Location = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] System.Drawing.Point(x, y)
LabelN.Text = LabelN.Name
LabelN.TextAlign = ContentAlignment.MiddleCenter
[/SIZE][SIZE=2][COLOR=#0000ff]AddHandler[/COLOR][/SIZE][SIZE=2] LabelN.Paint, [/SIZE][SIZE=2][COLOR=#0000ff]AddressOf[/COLOR][/SIZE][SIZE=2] PaintLabel
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].Controls.Add(LabelN)
[/SIZE][SIZE=2][COLOR=#0000ff]Me[/COLOR][/SIZE][SIZE=2].LabelList.Add(LabelN)
y += 38
 
[/SIZE][SIZE=2][COLOR=#0000ff]Next
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE]
[SIZE=2][COLOR=#0000ff]
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] PaintLabel([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] sender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Object[/COLOR][/SIZE][SIZE=2], [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] pe [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] PaintEventArgs)
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] c [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Label = sender
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] G [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Graphics = pe.Graphics
[/SIZE][SIZE=2][COLOR=#0000ff]Dim[/COLOR][/SIZE][SIZE=2] Rect [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Rectangle
Rect.Size = c.Size
Rect.Location = c.Location
[/SIZE][SIZE=2]G.FillRectangle(BBrush, Rect) [/SIZE][SIZE=2][COLOR=#008000]'This line should paint all the labels blue... but it doesn't !
[/COLOR][/SIZE][SIZE=2][COLOR=#008000]                  'What am I doing wrong here ???
[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub
End[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Class[/COLOR][/SIZE]

 
What is the value of BBrush in the last line? I would suggest putting your own brush and arguments in there to color it. I am not at home to compile this but just at a glance it appears that BBrush isn't blue, maybe?

All I am seeing and I may be wrong, is you are adding the labels then making them Black with White forecolor. Then later you are adding the paint handler.
When are you calling the repaint of these labels ect?... At first they are painted black, when are they re-painted? After the load event maybe, not sure. Put a breakpoint in the PaintLabel sub and find out what the values are and even if it's getting called at all.


If that is off course then I will compile and run the code at home to help you better. Also, if it's not too nosy, can I ask what all your are trying to accomplish here so that I can better visualize the whole process. I am with you on the code but I am not sure why your are adding the labels at run time ect.... That's just for curiousity.
 
This code is just a test snippet to help me figure out why a similar process wasn't working in my program. I cut it down and simplifed things to help me trouble-shoot. The value of BBrush is defined at the beginning of the class and is 'system.drawing.color.blue'. The labels are given an initial background & foreground color just so they are visible on the form now. If this paint event handler actually worked, I wouldn't have defined those values at all.
The paint process is a little more complicated in the actual program, but if I can get this to work, it's just a matter of a few changes. As far as calling the paint event handler directly... I'm not. I assumed that .NET calls it when the form is displayed or needs to be redrawn. I have put a break point in the paint handler and it goes through the code as it should... but the display just shows the unaltered labels.
I can do this same task with a single label, and the paint event handler works just fine. For example, the following code executes perfectly, and appears to be essentially the same.
VB.NET:
Public Class Form1
    Inherits System.Windows.Forms.Form
 
    Dim BBrush As New System.Drawing.SolidBrush(Color.Blue)
 
#Region " Windows Form Designer generated code "
    Public Sub New()
        MyBase.New()
               InitializeComponent()
      End Sub
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
 
    Private components As System.ComponentModel.IContainer
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(344, 237)
        Me.Name = "Form1"
        Me.Text = "Form1"
    End Sub
#End Region
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SetUpLabel()
    End Sub
 
    Private Sub SetUpLabel()
        Dim L As New Label
        L.Size = New Size(128, 64)
        L.Location = New Point(32, 32)
        AddHandler L.Paint, AddressOf PaintLabel
        Me.Controls.Add(L)
    End Sub
 
    Private Sub PaintLabel(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim rect As New Rectangle
        Dim c As Label = sender
        Dim g As Graphics = e.Graphics
        rect.Size = c.Size
        rect.Location = c.Location
        g.FillRectangle(BBrush, rect)
    End Sub
End Class
 
O i think I got it.
VB.NET:
 Private Sub PaintLabel(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim rect As New Rectangle
        Dim c As Label = sender
        Dim g As Graphics = e.Graphics
        rect.Size = c.Size
        [COLOR=red]rect.Location = c.Location
[/COLOR]     g.FillRectangle(BBrush, rect)
    End Sub

That is the location on the form, so the rectangle is being drawn off of the label. YOu need to draw the rect on the label so just make the location(0,0)

Try that and let me know...:)

Yes, I am testing the code now and I am pretty sure that's the problem.

replace the red line above with...
VB.NET:
[SIZE=2]rect.Location = [/SIZE][SIZE=2][COLOR=#0000ff]New[/COLOR][/SIZE][SIZE=2] Point(0, 0)
[/SIZE]

If you notice the entire label was never getting drawn. I have built a label on the form with the IDE with the same points as the one in your code and that is correct. The label was never getting completely drawn. Also, as you put more labels the location changes so no other labels will recieve the rectangle being drawn. Which is why you only ever got one... or part of one should i say.
 
Just as an added side note. 2 things, first you should always specify a type when declaring varaibles

VB.NET:
Dim LabelBrush as new solidBrush(color.blue)
Second of all if you a casting to a type then you should explicitly cast to that type.

VB.NET:
dim c as label = directcast(sender,label)

Also i'm interested to know, there doesn't appear to be a handles clause on the end of your PaintLabel sub, and you've added a handler to an for an event where there is a perfectly suffieicnt event in the label class. You do realise that a label raises it's own paint event, and that you can set it's control style bits to control how the painting is done. In addition you can add the handles clause to this paint event or use addhandler, for all the labels in your arraylist and then use the sender argument to determin which one raised the event?
 
Well vis he is adding the labels at runtime and there are multiple labels. That was just a breakdown to figure out the problem. It would be too much work to write that code into several label events rather than just one. And the default label event dosn't have the Handles clause b/c it was added at runtime. So the IDE can't help us auto generate it and you can't add that code when the label isn't already existing. Thus Sub PaintLabel() is the default paint event sub, just renamed. Or maybe I'm miss understanding you.

Also, it is wiser to program with Option Strict On, in my opinion, just as Vis mentioned and use DirectCast() to cast variables. Some times you may convert a variable and need to use Ctype() in which the IDE wants to auto generate but DirectCast is faster and prefferred if you can use it.
 
:D !!! YES !!! Thank You very much !!!:D
I have been looking at this code for two days now, and knew I was overlooking something very basic. Sometimes I can't see the forest for the trees. I appreciate your taking the time to solve this for me.

... As for using "Option Strict"... This is my first vb.NET application, and I started with Option Strict off because I didn't know it existed. I'm afraid to turn it on now for fear it will cause me to redo most of my code. I suppose I'll have to turn it on eventually. :rolleyes:

--- Thanks again !!!
 
No biggy and no rule saying you have to have it on. Your app will operate just fine with it off and it is measured into the VB flexability. It's just more optimal for when comiled for it to be on. You keep it off as long as you like and turn it on when you know more about it and are comfortable. Suggestion though, since you are starting to work with controls at the programming level and using your own painting events ect.. i would turn it on for better performance.

As for re=doing code, no such thing. All you will have to do is go back and add specific casting or conversion to certain variables and all. Try it for kicks... :)
 
'Kinda makes me wonder why that second code snippet works, and the first one doesn't. They both use the same: "rect.Location = c.Location"
 
Just as added information, the System.Windows.Forms.PaintEventArgs (argument e) includes a property that holds the rectangle in which to paint, the System.Windows.Forms.PaintEventArgs.ClipRectangle property.
Both of the lines of code below should work:
VB.NET:
e.Graphics.Clear(Color.Blue)
e.Graphics.FillRectangle(BBrush, e.ClipRectangle)

Also be sure to dispose of the brush and graphics objects when you're done with them. As my mom said, "Clean up after yourself".
 
You don't dispose the graphics provided by the Paint event. You only dispose graphics objects you create yourself, like CreateGraphics and Graphics.FromImage and such.
 
Back
Top