Slate Tabs

Overview Author Syntopia In this tutorial I show you how to make tabs. There are many ways to do this. With a checkbox or button style change, but for me it was the easiest way. Code: MyStyle.h // ...

Updated over 4 years ago Edit Page Revisions

Overview

Author Syntopia

In this tutorial I show you how to make tabs. There are many ways to do this. With a checkbox or button style change, but for me it was the easiest way.

File:Tabs.png

Code:

MyStyle.h

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#pragma once

class FMyStyle 
{
public:
    static void Initialize();
    static void Shutdown();

    static const ISlateStyle& Get();

    static TSharedPtr StylePtr;

};

MyStyle.cpp

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "TabbedView.h"
#include "MyStyle.h"
#include "Engine.h"
#include "SlateBasics.h"
#include "SlateStyle.h"

#define IMAGE_BRUSH(RelativePath, ...)  FSlateImageBrush(Style->RootToContentDir(RelativePath, TEXT(".png")), __VA_ARGS__)

TSharedPtr CreateStyle()
{
    TSharedPtr Style = MakeShareable(new FSlateStyleSet("PreloadStyle"));
    Style->SetContentRoot(FPaths::GameContentDir() / "Slate");

    Style->Set("tab_normal", new IMAGE_BRUSH("tab_normal", FVector2D(256, 64)));
    Style->Set("tab_active", new IMAGE_BRUSH("tab_active", FVector2D(256, 64)));

    return Style;
}

#undef IMAGE_BRUSH

TSharedPtr FMyStyle::StylePtr = NULL;

void FMyStyle::Initialize()
{
    if (!StylePtr.IsValid())
    {
        StylePtr = CreateStyle();
        FSlateStyleRegistry::RegisterSlateStyle(*StylePtr);
    }
}

void FMyStyle::Shutdown()
{
    FSlateStyleRegistry::UnRegisterSlateStyle(*StylePtr);
    ensure(StylePtr.IsUnique());
    StylePtr.Reset();
}

const ISlateStyle& FMyStyle::Get()
{
    return *StylePtr;   
}

TabbedView.h

#pragma once

#include "Engine.h"

TabbedView.cpp

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "TabbedView.h"
#include "MyStyle.h"

class MyModule : public FDefaultGameModuleImpl
{
public:
    virtual void StartupModule() override
    {
        FSlateStyleRegistry::UnRegisterSlateStyle("PreloadStyle");
        FMyStyle::Initialize();
    }

    virtual void ShutdownModule() override
    {
        FMyStyle::Shutdown();
    }
};

IMPLEMENT_PRIMARY_GAME_MODULE(MyModule, TabbedView, "TabbedView");

MyGameMode.h

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#pragma once

#include "MyGameMode.generated.h"

UCLASS(minimalapi)
class AMyGameMode : public AGameMode
{
    GENERATED_UCLASS_BODY()

};

MyGameMode.cpp

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "TabbedView.h"
#include "MyGameMode.h"
#include "MyHUD.h"

AMyGameMode::AMyGameMode(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    // use our custom HUD class
    HUDClass = AMyHUD::StaticClass();
}

MyHUD.h

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.
#pragma once 

#include "MyHUD.generated.h"

class SMyUIWidget : public SCompoundWidget
{
    SLATE_BEGIN_ARGS(SMyUIWidget)
    {}
    /*See private declaration of OwnerHUD below.*/
    SLATE_ARGUMENT(TWeakObjectPtr, OwnerHUD)
    /** The visual style of the button */
    SLATE_END_ARGS()
 
public:
    void Construct(const FArguments& InArgs);

    FReply FirstTabClicked();
    FReply SecondTabClicked();

    const FSlateBrush* GetFirstImageBrush() const;
    const FSlateBrush* GetSecondImageBrush() const;

private:
    TWeakObjectPtr OwnerHUD;

    int32 TabIndex;

    int32 GetCurrentTabIndex() const
    {
        return TabIndex;
    }
    
};

UCLASS()
class AMyHUD : public AHUD
{
    GENERATED_UCLASS_BODY()

public:
    void BeginPlay();

    virtual void DrawHUD() override;

private:
    TSharedPtr MyUIWidget;

};

MyHUD.cpp

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.

#include "TabbedView.h"
#include "MyHUD.h"
#include "SWidgetSwitcher.h"
#include "MyStyle.h"

int FirstTabActive  = 1;
int SecondTabActive = 0;

int ftClick = 1;
int stClick = 0;

void SMyUIWidget::Construct(const FArguments& InArgs)
{
    OwnerHUD = InArgs._OwnerHUD;

    TabIndex = 0;

    ChildSlot
        [
            SNew(SVerticalBox) 
            + SVerticalBox::Slot()
            .FillHeight(0.1)

            + SVerticalBox::Slot()
            .FillHeight(0.8)
            [
                SNew(SHorizontalBox)

                + SHorizontalBox::Slot()
                .FillWidth(0.3)

                + SHorizontalBox::Slot()
                .FillWidth(0.4)
                [
                    SNew(SVerticalBox)
                    + SVerticalBox::Slot()
                    .FillHeight(0.2)
                    [
                        SNew(SHorizontalBox)
                        + SHorizontalBox::Slot()
                        [
                            SNew(SButton)
                            .ContentPadding(-3)
                            .OnClicked(this, &SMyUIWidget::FirstTabClicked)
                            [
                                SNew(SVerticalBox)
                                + SVerticalBox::Slot()
                                .HAlign(HAlign_Fill)
                                .VAlign(VAlign_Fill)
                                [
                                    SNew(SBorder)
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    .BorderImage(this, &SMyUIWidget::GetFirstImageBrush)
                                    [
                                        SNew(STextBlock)
                                        .Font(FSlateFontInfo("Veranda", 54))
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Text(FText::FromString("Page One"))
                                    ]
                                ]
                            ]
                        ]

                        + SHorizontalBox::Slot()
                        .FillWidth(0.1)

                        + SHorizontalBox::Slot()
                        [
                            SNew(SButton)
                            .ContentPadding(-3)
                            .OnClicked(this, &SMyUIWidget::SecondTabClicked)
                            [
                                SNew(SVerticalBox)
                                + SVerticalBox::Slot()
                                .HAlign(HAlign_Fill)
                                .VAlign(VAlign_Fill)
                                [
                                    SNew(SBorder)
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    .BorderImage(this, &SMyUIWidget::GetSecondImageBrush)
                                    [
                                        SNew(STextBlock)
                                        .Font(FSlateFontInfo("Veranda", 54))
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Text(FText::FromString("Page Two"))
                                    ]
                                ]
                            ]
                        ]
                    ]

                    + SVerticalBox::Slot()
                    .FillHeight(0.8)
                    [
                        SNew(SWidgetSwitcher)
                        .WidgetIndex(this, &SMyUIWidget::GetCurrentTabIndex)
                        + SWidgetSwitcher::Slot() 
                        [
                            SNew(SBorder)
                            .BorderImage(FCoreStyle::Get().GetBrush("ToolPanel.GroupBorder"))
                            [
                                SNew(SVerticalBox)
                                + SVerticalBox::Slot()
                                .HAlign(HAlign_Center)
                                .VAlign(VAlign_Center)
                                [
                                    SNew(STextBlock)
                                    .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                    .Font(FSlateFontInfo("Veranda", 72))
                                    .Text(FText::FromString("Page One"))
                                ]
                                + SVerticalBox::Slot()
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    [
                                        SNew(STextBlock)
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Font(FSlateFontInfo("Veranda", 52))
                                        .Text(FText::FromString("Page One"))
                                    ]
                                + SVerticalBox::Slot()
                                .HAlign(HAlign_Center)
                                .VAlign(VAlign_Center)
                                [
                                    SNew(STextBlock)
                                    .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                    .Font(FSlateFontInfo("Veranda", 32))
                                    .Text(FText::FromString("Page One"))
                                ]
                            ]
                        ]
                        + SWidgetSwitcher::Slot() // Weapons
                            [
                                SNew(SBorder)
                                .BorderImage(FCoreStyle::Get().GetBrush("ToolPanel.GroupBorder"))
                                [
                                    SNew(SVerticalBox)
                                    + SVerticalBox::Slot()
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    [
                                        SNew(STextBlock)
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Font(FSlateFontInfo("Veranda", 72))
                                        .Text(FText::FromString("Page Two"))
                                    ]
                                    + SVerticalBox::Slot()
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    [
                                        SNew(STextBlock)
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Font(FSlateFontInfo("Veranda", 52))
                                        .Text(FText::FromString("Page Two"))
                                    ]
                                    + SVerticalBox::Slot()
                                    .HAlign(HAlign_Center)
                                    .VAlign(VAlign_Center)
                                    [
                                        SNew(STextBlock)
                                        .ColorAndOpacity(FLinearColor(1, 1, 1, 1))
                                        .Font(FSlateFontInfo("Veranda", 32))
                                        .Text(FText::FromString("Page Two"))
                                    ]
                                ]
                            ]
                    ]
                ]

                + SHorizontalBox::Slot()
                .FillWidth(0.3)
            ]

            + SVerticalBox::Slot()
            .FillHeight(0.1)
        ];
}

const FSlateBrush* SMyUIWidget::GetFirstImageBrush() const
{
    FName BrushName;
    (FirstTabActive == 0) ? BrushName = TEXT("tab_normal") : BrushName = TEXT("tab_active");

    return FMyStyle::Get().GetBrush(BrushName);
}

const FSlateBrush* SMyUIWidget::GetSecondImageBrush() const
{
    FName BrushName;
    (SecondTabActive == 0) ? BrushName = TEXT("tab_normal") : BrushName = TEXT("tab_active");

    return FMyStyle::Get().GetBrush(BrushName);
}

AMyHUD::AMyHUD(const FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{

}

void AMyHUD::BeginPlay()
{
    SAssignNew(MyUIWidget, SMyUIWidget).OwnerHUD(this);

    if (GEngine->IsValidLowLevel())
    {
        GEngine->GameViewport->AddViewportWidgetContent(SNew(SWeakWidget).PossiblyNullContent(MyUIWidget.ToSharedRef()));
    }
 
    if (MyUIWidget.IsValid())
    {
        MyUIWidget->SetVisibility(EVisibility::Visible);
    }
}

void AMyHUD::DrawHUD()
{
    Super::DrawHUD();
}

FReply SMyUIWidget::FirstTabClicked()
{
    TabIndex = 0;

    stClick = 0;
    ftClick++;

    if (ftClick == 1)
    {
        if (FirstTabActive == 0)
        {
            FirstTabActive = 1;
            SecondTabActive = 0;
        }

    }

    return FReply::Handled();
}

FReply SMyUIWidget::SecondTabClicked()
{
    TabIndex = 1;

    ftClick = 0;
    stClick++;

    if (stClick == 1)
    {
        if (SecondTabActive == 0)
        {
            FirstTabActive = 0;
            SecondTabActive = 1;
        }

    }

    return FReply::Handled();
}

Summary

Set your level to use your new game mode, and run!

Source code:

File:TabbedView.zip

(~67KB)