How to add a new tab ? (TabbedComponent)[SOLVED]


#1

Hello,

I want to create a symply application because i am a beginner with JUCE, i use the Demo project to help me to code my first component.

I have create an application who display Tabbedcomponent with MenuBar, i want to add a tab by my menu.

Mainwindow.cpp

class ContentComp  :    public Component,
public MenuBarModel,
public ApplicationCommandTarget
{
public:
    ContentComp (MainAppWindow& mainWindow_)
    : mainWindow (mainWindow_),
    currentDemoId (0)
    {
        setOpaque (true);
        invokeDirectly (showWidgets, true);
    }
    ~ContentComp()
    {
        deleteAllChildren();
    }
    void paint (Graphics& g)
    {
        g.fillAll (Colours::grey);
    }
    
    void resized()
    {
        if (currentDemo != nullptr)
        {
            currentDemo->setBounds (getLocalBounds());
        }
    }
    void showTab(Component* tabComp)
    {
        currentDemo = tabComp;
        addAndMakeVisible (currentDemo);
        resized();
    }
    StringArray getMenuBarNames()
    {
        const char* const names[] = { "menu", nullptr };
        return StringArray (names);
    }

    PopupMenu getMenuForIndex (int menuIndex, const String& /*menuName*/)
    {
        //liaison entre la vue et le controleur
        ApplicationCommandManager* commandManager = &(mainWindow.commandManager);
        
        PopupMenu menu;
        
        if (menuIndex == 0)
        {
            menu.addCommandItem (commandManager, showWidgets);
            menu.addCommandItem (commandManager, showAudio);
            menu.addSeparator();
            menu.addCommandItem (commandManager, newFile);
        }
        
        return menu;
    }
    void menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/)
    {
        // most of our menu items are invoked automatically as commands, but we can handle the
        // other special cases here..
        
        
        if (menuItemID >= 5001 && menuItemID < 5010)
        {
            const int engineIndex = menuItemID - 5001;
            
#if JUCE_OPENGL
            if (engineIndex >= getPeer()->getAvailableRenderingEngines().size())
            {
                setUsingOpenGLRenderer (true);
                return;
            }
#endif
            
            setUsingOpenGLRenderer (false);
            getPeer()->setCurrentRenderingEngine (engineIndex);
        }
    }
    
    void setUsingOpenGLRenderer (bool shouldUseOpenGL)
    {
        
    }
    
    //==============================================================================
    // The following methods implement the ApplicationCommandTarget interface, allowing
    // this window to publish a set of actions it can perform, and which can be mapped
    // onto menus, keypresses, etc.
    
    ApplicationCommandTarget* getNextCommandTarget()
    {
        // this will return the next parent component that is an ApplicationCommandTarget (in this
        // case, there probably isn't one, but it's best to use this method in your own apps).
        return findFirstTargetParentComponent();
    }
    
    void getAllCommands (Array <CommandID>& commands)
    {
        // this returns the set of all commands that this target can perform..
        const CommandID ids[] = {
            showAudio,
            newFile,
            showWidgets      
        };
        
        commands.addArray (ids, numElementsInArray (ids));
    }
    
    // This method is used when something needs to find out the details about one of the commands
    // that this object can perform..
    void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result)
    {
        const String generalCategory ("General");
        const String demosCategory ("Demos");
        
        switch (commandID)
        {
            case newFile:
                result.setInfo ("New", String::empty, demosCategory, 0);
                result.setTicked (currentDemoId == newFile);
                result.addDefaultKeypress ('n', ModifierKeys::commandModifier);
                break;
            
            case showAudio:
                result.setInfo ("Audio", "Shows Audio selector", demosCategory, 0);
                result.setTicked (currentDemoId == showAudio);
                result.addDefaultKeypress ('.', ModifierKeys::commandModifier);
                break;
            case showWidgets:
                result.setInfo ("Widgets", "Shows the widgets demo", demosCategory, 0);
                result.setTicked (currentDemoId == showWidgets);
                result.addDefaultKeypress ('1', ModifierKeys::commandModifier);
                break;
                
            default:
                break;
        };
    }
    bool perform (const InvocationInfo& info)
    {
        Component* comp = createTab();
        switch (info.commandID)
        {
                
            case showWidgets:
                //showTab (createTab());
                currentDemoId = showWidgets;
                break;
            case showAudio:
                AlertWindow::showMessageBox(AlertWindow::NoIcon, "Message","Ouvrir fichier");
                break;
            case newFile:
                ((DemoTabbedComponent*) comp)->addNewTabb();
                ((DemoTabbedComponent*) comp)->repaint();
                showTab (createTab());
                //test->postCommandMessage(10);
                AlertWindow::showMessageBox(AlertWindow::NoIcon, "Message","New fichier");
                break;
                
            default:
                return false;
        };
        
        return true;
    }
private:
    MainAppWindow& mainWindow;
    ScopedPointer<Component> currentDemo;
    int currentDemoId;
    
#if JUCE_OPENGL
    OpenGLContext openGLContext;
#endif
    
    TooltipWindow tooltipWindow; // to add tooltips to an application, you
    // just need to create one of these and leave it
    // there to do its work..
    
    //==============================================================================
    StringArray getRenderingEngines()
    {
        StringArray renderingEngines (getPeer()->getAvailableRenderingEngines());
        
#if JUCE_OPENGL
        renderingEngines.add ("Use OpenGL Renderer");
#endif
        
        return renderingEngines;
    }
    
    //==============================================================================
    enum CommandIDs
    {
        
        showAudio                  = 0x1000,
        showWidgets                = 0x2000,
        newFile                    = 0x2006
    };
    
    //JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ContentComp)
};
static ScopedPointer<ApplicationCommandManager> applicationCommandManager;
static ScopedPointer<AudioDeviceManager> sharedAudioDeviceManager;

//==============================================================================
MainAppWindow::MainAppWindow()
    : DocumentWindow (JUCEApplication::getInstance()->getApplicationName(),
                      Colours::lightgrey,
                      DocumentWindow::allButtons)
{
    setResizable (true, false); // resizability is a property of ResizableWindow
    setResizeLimits (805, 700, 8192, 8192);
    centreWithSize (805, 700);
    setVisible (true);
    contentComp = new ContentComp (*this);
    //permet de recuper les commandes que le composant recoit
    commandManager.registerAllCommandsForTarget (contentComp);
    commandManager.registerAllCommandsForTarget (JUCEApplication::getInstance());
    addKeyListener (commandManager.getKeyMappings());
    
    // sets the main content component for the window to be this tabbed
    // panel. This will be deleted when the window is deleted.
    setContentOwned (contentComp, false);
    
    // this tells the DocumentWindow to automatically create and manage a MenuBarComponent
    // which uses our contentComp as its MenuBarModel
    setMenuBar (contentComp);
    
    // tells our menu bar model that it should watch this command manager for
    // changes, and send change messages accordingly.
    contentComp->setApplicationCommandManagerToWatch (&commandManager);
    
    setVisible (true);
}

MainAppWindow::~MainAppWindow()
{
    deleteAllChildren();
    delete contentComp;
}

void MainAppWindow::closeButtonPressed()
{
    JUCEApplication::getInstance()->systemRequestedQuit();
}

and TabComponent.cpp

#include "TabComponent.h"

DemoTabbedComponent::DemoTabbedComponent()
: TabbedComponent (TabbedButtonBar::TabsAtTop)
{
    //ajout d'un onglet qui contient un composant
    addTab ("Projet 0", Colours::darkgrey, NULL, true);
}
DemoTabbedComponent::~DemoTabbedComponent()
{
    //deleteAllChildren();
}
    // methode obligatoire à implémeter :  ButtonListener
void DemoTabbedComponent::buttonClicked (Button* button)
{
        
}
void DemoTabbedComponent::addNewTabb()
{
    printf("added !");
    addTab ("test", Colours::darkgrey, NULL,    true);
}
Component* createTab()
{
    return new DemoTabbedComponent();
}

I try to add a new tab in my component with :

bool perform (const InvocationInfo& info)
    {
        Component* comp = createTab();
        switch (info.commandID)
        {
          case newFile: 
              ((DemoTabbedComponent*) comp)->addNewTabb(); 
              ((DemoTabbedComponent*) comp)->repaint(); 
              showTab (createTab());
              AlertWindow::showMessageBox(AlertWindow::NoIcon, "Message","New fichier"); 
          break;
 ....

 

But nothing change in my component... any idee ?

Also, when i close my application it crash (ContainerDeletePolicy 0


#2
case newFile:
                if (comp == nullptr)
                {
                    comp = createTab();
                    i = 0;
                    name += i;
                   ((DemoTabbedComponent*) comp)->addNewTabb(name);
                   ((DemoTabbedComponent*) comp)->repaint();
                    showTab(comp);
                }
                else
                {
                    i++;
                    name += i;
                    ((DemoTabbedComponent*) comp)->addNewTabb(name);
                    ((DemoTabbedComponent*) comp)->repaint();
                    showTab(comp);
                }
                break;

This is my solution ;)