/*
  ==============================================================================

   This file is part of the JUCE library - "Jules' Utility Class Extensions"
   Copyright 2004-6 by Raw Material Software ltd.

  ------------------------------------------------------------------------------

   JUCE can be redistributed and/or modified under the terms of the
   GNU General Public License, as published by the Free Software Foundation;
   either version 2 of the License, or (at your option) any later version.

   JUCE is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with JUCE; if not, visit www.gnu.org/licenses or write to the
   Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
   Boston, MA 02111-1307 USA

  ------------------------------------------------------------------------------

   If you'd like to release a closed-source product which uses JUCE, commercial
   licenses are also available: visit www.rawmaterialsoftware.com/juce for
   more information.

  ==============================================================================
*/

#include "jucedemo_headers.h"
#include "MainDemoWindow.h"


//==============================================================================
class SourceCodeWindow;
static SourceCodeWindow* sourceWindow = 0;


//==============================================================================
class SourceCodeWindow  : public DialogWindow
{
    TextEditor* textBox;

public:
    SourceCodeWindow()
        : DialogWindow (T("JUCE Demo Source Code!"),
                        Colours::floralwhite,
                        false)
    {
        setContentComponent (textBox = new TextEditor());

        textBox->setColours (Colours::black, Colours::white);
        textBox->setMultiLine (true, false);
        textBox->setReturnKeyStartsNewLine (true);

        setResizable (true, true); // we'll choose a corner-resizer component for this window,
                                   // as a contrast to the resizable border on the main window
    }

    ~SourceCodeWindow()
    {
        // the text editor gets deleted automatically because it's the
        // window's content component.

        sourceWindow = 0;
    }

    void closeButtonPressed()
    {
        delete this;
    }

    void updateSourceCode (const String& text)
    {
        Font font (14.0f);
        font.setTypefaceName (Font::getDefaultMonospacedFontName());
        textBox->setFont (font);

        textBox->setText (text);

        toFront (true);
    }
};

//==============================================================================
const int maxDemos = 20;


class ContentComp  : public Component,
                     public MenuBarModel
{
    //==============================================================================
    MainDemoWindow* mainWindow;

    ShinyLookAndFeel shinyLookAndFeel;
    bool isDefaultLookAndFeel;

    Component* demos[maxDemos];
    Component* currentDemo;
    int currentDemoId;
    const char* demoSourceCodeText;

    TooltipWindow tooltipWindow; // to add tooltips to an application, you
                                 // just need to create one of these and leave it
                                 // there to do its work..

public:
    //==============================================================================
    ContentComp (MainDemoWindow* mainWindow_)
        : mainWindow (mainWindow_)
    {
        LookAndFeel::setDefaultLookAndFeel (&shinyLookAndFeel);
        isDefaultLookAndFeel = false;

        demoSourceCodeText = 0;

        for (int i = 0; i < maxDemos; ++i)
            demos[i] = 0;

        currentDemo = 0;

        showDemo (3);
    }

    ~ContentComp()
    {
        for (int i = 0; i < maxDemos; ++i)
            if (demos[i] != 0)
                delete demos[i];

        deleteAllChildren();

        deleteAndZero (sourceWindow);
    }

    //==============================================================================
    void resized()
    {
        if (currentDemo != 0)
            currentDemo->setBounds (0, 0, getWidth(), getHeight());
    }

    //==============================================================================
    void showDemo (const int demoId)
    {
        if (currentDemo != 0)
            removeChildComponent (currentDemo);

        currentDemo = 0;
        currentDemoId = demoId;

        if (demos[demoId] == 0)
        {
            switch (demoId)
            {
            case 1:
                demos[demoId] = createPathsAndTransformsDemo();
                break;

            case 2:
                demos[demoId] = createFontsAndTextDemo();
                break;

            case 3:
                demos[demoId] = createWidgetsDemo();
                break;

            case 4:
                demos[demoId] = createThreadingDemo();
                break;

            case 5:
                demos[demoId] = createTreeViewDemo();
                break;

            case 6:
                demos[demoId] = createAudioDemo();
                break;

            case 7:
                demos[demoId] = createDragAndDropDemo();
                break;

#if JUCE_OPENGL
            case 8:
                demos[demoId] = createOpenGLDemo();
                break;
#endif

#if JUCE_QUICKTIME && ! JUCE_LINUX
            case 9:
                demos[demoId] = createQuickTimeDemo();
                break;
#endif

            case 10:
                demos[demoId] = createInterprocessCommsDemo();
                break;
            }
        }

        switch (demoId)
        {
        case 1:
            demoSourceCodeText = BinaryData::pathsandtransformsdemo_cpp;
            break;

        case 2:
            demoSourceCodeText = BinaryData::fontsandtextdemo_cpp;
            break;

        case 3:
            demoSourceCodeText = BinaryData::widgetsdemo_cpp;
            break;

        case 4:
            demoSourceCodeText = BinaryData::threadingdemo_cpp;
            break;

        case 5:
            demoSourceCodeText = BinaryData::treeviewdemo_cpp;
            break;

        case 6:
            demoSourceCodeText = BinaryData::audiodemo_cpp;
            break;

        case 7:
            demoSourceCodeText = BinaryData::draganddropdemo_cpp;
            break;

#if JUCE_OPENGL
        case 8:
            demoSourceCodeText = BinaryData::opengldemo_cpp;
            break;
#endif

#if JUCE_QUICKTIME && ! JUCE_LINUX
        case 9:
            demoSourceCodeText = BinaryData::quicktimedemo_cpp;
            break;
#endif

        case 10:
            demoSourceCodeText = BinaryData::interprocesscommsdemo_cpp;
            break;
        }

        currentDemo = demos[demoId];
        addAndMakeVisible (currentDemo);

        resized();
    }

    void showSource()
    {
        if (sourceWindow == 0)
        {
            sourceWindow = new SourceCodeWindow();
            sourceWindow->centreAroundComponent (this, 750, 600);
            sourceWindow->setVisible (true);
        }

        sourceWindow->updateSourceCode (demoSourceCodeText);
    }

    //==============================================================================
    const StringArray getMenuBarNames (MenuBarComponent* menuBar)
    {
        const tchar* const names[] = { T("Demo"), T("Source Code"), T("Look-and-feel"), 0 };

        return StringArray ((const tchar**) names);
    }

    const PopupMenu getMenuForIndex (MenuBarComponent* menuBar,
                                     int menuIndex,
                                     const String& menuName)
    {
        PopupMenu menu;

        if (menuIndex == 0)
        {
            menu.addItem (1, T("Paths and Transforms"), true, currentDemoId == 1);
            menu.addItem (2, T("Fonts and Text"), true, currentDemoId == 2);
            menu.addItem (3, T("Widgets"), true, currentDemoId == 3);
            menu.addItem (4, T("Multithreading"), true, currentDemoId == 4);
            menu.addItem (5, T("Treeviews"), true, currentDemoId == 5);
            menu.addItem (6, T("Audio"), true, currentDemoId == 6);
            menu.addItem (7, T("Drag-and-Drop"), true, currentDemoId == 7);
#if JUCE_OPENGL
            menu.addItem (8, T("OpenGL"), true, currentDemoId == 8);
#endif

#if JUCE_QUICKTIME && ! JUCE_LINUX
            menu.addItem (9, T("QuickTime"), true, currentDemoId == 9);
#endif
            menu.addItem (10, T("Interprocess Communication"), true, currentDemoId == 10);

            menu.addSeparator();
            menu.addItem (99, T("Quit"));
        }
        else if (menuIndex == 1)
        {
            menu.addItem (100, T("show the source code for this demo"));
        }
        else if (menuIndex == 2)
        {
            menu.addItem (1001, T("original look-and-feel"), true, isDefaultLookAndFeel);
            menu.addItem (1002, T("shiny look-and-feel"), true, ! isDefaultLookAndFeel);
            menu.addSeparator();
            menu.addItem (1003, T("use native window title bar"), true, mainWindow->isUsingNativeTitleBar());
        }

        return menu;
    }

    void menuItemSelected (MenuBarComponent* menuBar,
                           int menuItemID,
                           int index)
    {
        if (menuItemID == 99)
        {
            JUCEApplication::quit();
        }
        else if (menuItemID < 100)
        {
            showDemo (menuItemID);
        }
        else if (menuItemID == 100)
        {
            showSource();
        }
        else if (menuItemID == 1001)
        {
            LookAndFeel::setDefaultLookAndFeel (0);
            isDefaultLookAndFeel = true;
        }
        else if (menuItemID == 1002)
        {
            LookAndFeel::setDefaultLookAndFeel (&shinyLookAndFeel);
            isDefaultLookAndFeel = false;
        }
        else if (menuItemID == 1003)
        {
            mainWindow->setUsingNativeTitleBar (! mainWindow->isUsingNativeTitleBar());
        }
    }
};

//==============================================================================
MainDemoWindow::MainDemoWindow()
    : DocumentWindow (T("JUCE Demo!"),
                      Colours::azure,
                      DocumentWindow::allButtons,
                      true)
{
    setResizable (true, false); // resizability is a property of ResizableWindow

    ContentComp* contentComp = new ContentComp (this);

    // sets the main content component for the window to be this tabbed
    // panel. This will be deleted when the window is deleted.
    setContentComponent (contentComp);

    // this tells the DocumentWindow to automatically create and manage a MenuBarComponent
    // which uses our contentComp as its MenuBarModel
    setMenuBar (contentComp);
}

MainDemoWindow::~MainDemoWindow()
{
    // our content component will get deleted by the DialogWindow base class,
    // and that will clean up the other demo components.
}

void MainDemoWindow::closeButtonPressed()
{
    // The correct thing to do when you want the app to quit is to call the
    // JUCEApplication::systemRequestedQuit() method.

    // That means that requests to quit that come from your own UI, or from other
    // OS-specific sources (e.g. the dock menu on the mac) all get handled in the
    // same way.

    JUCEApplication::getInstance()->systemRequestedQuit();
}
