/**
 * @file lltoolbarview.cpp
 * @author Merov Linden
 * @brief User customizable toolbar class
 *
 * $LicenseInfo:firstyear=2011&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2011, Linden Research, Inc.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#include "llviewerprecompiledheaders.h"

#include "lltoolbarview.h"

#include "llappviewer.h"
#include "llbutton.h"
#include "llclipboard.h"
#include "lldir.h"
#include "lldockablefloater.h"
#include "lldockcontrol.h"
#include "llimview.h"
#include "lltransientfloatermgr.h"
#include "lltoolbar.h"
#include "lltooldraganddrop.h"
#include "llxmlnode.h"

#include "llagent.h"  // HACK for destinations guide on startup
#include "llfloaterreg.h"  // HACK for destinations guide on startup
#include "llviewercontrol.h"  // HACK for destinations guide on startup
#include "llinventorymodel.h" // HACK to disable starter avatars button for NUX

LLToolBarView* gToolBarView = NULL;

static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view");

bool isToolDragged()
{
    return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER);
}

LLToolBarView::Toolbar::Toolbar()
:   button_display_mode("button_display_mode"),
    commands("command")
{}

LLToolBarView::ToolbarSet::ToolbarSet()
:   left_toolbar("left_toolbar"),
    right_toolbar("right_toolbar"),
    bottom_toolbar("bottom_toolbar")
{}


LLToolBarView::LLToolBarView(const LLToolBarView::Params& p)
:   LLUICtrl(p),
    mDragStarted(false),
    mShowToolbars(true),
    mDragToolbarButton(NULL),
    mDragItem(NULL),
    mToolbarsLoaded(false),
    mBottomToolbarPanel(NULL)
{
    for (S32 i = 0; i < LLToolBarEnums::TOOLBAR_COUNT; i++)
    {
        mToolbars[i] = NULL;
    }
}

void LLToolBarView::initFromParams(const LLToolBarView::Params& p)
{
    // Initialize the base object
    LLUICtrl::initFromParams(p);
}

LLToolBarView::~LLToolBarView()
{
    saveToolbars();
}

bool LLToolBarView::postBuild()
{
    mToolbars[LLToolBarEnums::TOOLBAR_LEFT] = getChild<LLToolBar>("toolbar_left");
    mToolbars[LLToolBarEnums::TOOLBAR_LEFT]->getCenterLayoutPanel()->setLocationId(LLToolBarEnums::TOOLBAR_LEFT);

    mToolbars[LLToolBarEnums::TOOLBAR_RIGHT] = getChild<LLToolBar>("toolbar_right");
    mToolbars[LLToolBarEnums::TOOLBAR_RIGHT]->getCenterLayoutPanel()->setLocationId(LLToolBarEnums::TOOLBAR_RIGHT);

    mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM] = getChild<LLToolBar>("toolbar_bottom");
    mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM]->getCenterLayoutPanel()->setLocationId(LLToolBarEnums::TOOLBAR_BOTTOM);

    mBottomToolbarPanel = getChild<LLView>("bottom_toolbar_panel");

    for (int i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        mToolbars[i]->setStartDragCallback(boost::bind(LLToolBarView::startDragTool,_1,_2,_3));
        mToolbars[i]->setHandleDragCallback(boost::bind(LLToolBarView::handleDragTool,_1,_2,_3,_4));
        mToolbars[i]->setHandleDropCallback(boost::bind(LLToolBarView::handleDropTool,_1,_2,_3,_4));
        mToolbars[i]->setButtonAddCallback(boost::bind(LLToolBarView::onToolBarButtonAdded,_1));
        mToolbars[i]->setButtonRemoveCallback(boost::bind(LLToolBarView::onToolBarButtonRemoved,_1));
    }

    return true;
}

S32 LLToolBarView::hasCommand(const LLCommandId& commandId) const
{
    S32 command_location = LLToolBarEnums::TOOLBAR_NONE;

    for (S32 loc = LLToolBarEnums::TOOLBAR_FIRST; loc <= LLToolBarEnums::TOOLBAR_LAST; loc++)
    {
        if (mToolbars[loc]->hasCommand(commandId))
        {
            command_location = loc;
            break;
        }
    }

    return command_location;
}

S32 LLToolBarView::addCommand(const LLCommandId& commandId, LLToolBarEnums::EToolBarLocation toolbar, int rank)
{
    int old_rank;
    removeCommand(commandId, old_rank);

    S32 command_location = mToolbars[toolbar]->addCommand(commandId, rank);

    return command_location;
}

S32 LLToolBarView::removeCommand(const LLCommandId& commandId, int& rank)
{
    S32 command_location = hasCommand(commandId);
    rank = LLToolBar::RANK_NONE;

    if (command_location != LLToolBarEnums::TOOLBAR_NONE)
    {
        rank = mToolbars[command_location]->removeCommand(commandId);
    }

    return command_location;
}

S32 LLToolBarView::enableCommand(const LLCommandId& commandId, bool enabled)
{
    S32 command_location = hasCommand(commandId);

    if (command_location != LLToolBarEnums::TOOLBAR_NONE)
    {
        mToolbars[command_location]->enableCommand(commandId, enabled);
    }

    return command_location;
}

S32 LLToolBarView::stopCommandInProgress(const LLCommandId& commandId)
{
    S32 command_location = hasCommand(commandId);

    if (command_location != LLToolBarEnums::TOOLBAR_NONE)
    {
        mToolbars[command_location]->stopCommandInProgress(commandId);
    }

    return command_location;
}

S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */)
{
    S32 command_location = hasCommand(commandId);

    if (command_location != LLToolBarEnums::TOOLBAR_NONE)
    {
        mToolbars[command_location]->flashCommand(commandId, flash, force_flashing);
    }

    return command_location;
}

bool LLToolBarView::addCommandInternal(const LLCommandId& command, LLToolBar* toolbar)
{
    LLCommandManager& mgr = LLCommandManager::instance();
    if (mgr.getCommand(command))
    {
        toolbar->addCommand(command);
    }
    else
    {
        LL_WARNS()  << "Toolbars creation : the command with id " << command.uuid().asString() << " cannot be found in the command manager" << LL_ENDL;
        return false;
    }
    return true;
}

bool LLToolBarView::loadToolbars(bool force_default)
{
    LLToolBarView::ToolbarSet toolbar_set;
    bool err = false;

    // Load the toolbars.xml file
    std::string toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml");
    if (force_default)
    {
        toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml");
    }
    else if (!gDirUtilp->fileExists(toolbar_file))
    {
        LL_WARNS() << "User toolbars def not found -> use default" << LL_ENDL;
        toolbar_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "toolbars.xml");
    }

    LLXMLNodePtr root;
    if(!LLXMLNode::parseFile(toolbar_file, root, NULL))
    {
        LL_WARNS() << "Unable to load toolbars from file: " << toolbar_file << LL_ENDL;
        err = true;
    }

    if (!err && !root->hasName("toolbars"))
    {
        LL_WARNS() << toolbar_file << " is not a valid toolbars definition file" << LL_ENDL;
        err = true;
    }

    // Parse the toolbar settings
    LLXUIParser parser;
    if (!err)
    {
        parser.readXUI(root, toolbar_set, toolbar_file);
    }

    if (!err && !toolbar_set.validateBlock())
    {
        LL_WARNS() << "Unable to validate toolbars from file: " << toolbar_file << LL_ENDL;
        err = true;
    }

    if (err)
    {
        if (force_default)
        {
            LL_ERRS() << "Unable to load toolbars from default file : " << toolbar_file << LL_ENDL;
            return false;
        }

        // Try to load the default toolbars
        return loadToolbars(true);
    }

    // Clear the toolbars now before adding the loaded commands and settings
    for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        if (mToolbars[i])
        {
            mToolbars[i]->clearCommandsList();
        }
    }

    // Add commands to each toolbar
    if (toolbar_set.left_toolbar.isProvided() && mToolbars[LLToolBarEnums::TOOLBAR_LEFT])
    {
        if (toolbar_set.left_toolbar.button_display_mode.isProvided())
        {
            LLToolBarEnums::ButtonType button_type = toolbar_set.left_toolbar.button_display_mode;
            mToolbars[LLToolBarEnums::TOOLBAR_LEFT]->setButtonType(button_type);
        }
        for (const LLCommandId::Params& command_params : toolbar_set.left_toolbar.commands)
        {
            if (!addCommandInternal(LLCommandId(command_params), mToolbars[LLToolBarEnums::TOOLBAR_LEFT]))
            {
                LL_WARNS() << "Error adding command '" << command_params.name() << "' to left toolbar." << LL_ENDL;
            }
        }
    }
    if (toolbar_set.right_toolbar.isProvided() && mToolbars[LLToolBarEnums::TOOLBAR_RIGHT])
    {
        if (toolbar_set.right_toolbar.button_display_mode.isProvided())
        {
            LLToolBarEnums::ButtonType button_type = toolbar_set.right_toolbar.button_display_mode;
            mToolbars[LLToolBarEnums::TOOLBAR_RIGHT]->setButtonType(button_type);
        }
        for (const LLCommandId::Params& command_params : toolbar_set.right_toolbar.commands)
        {
            if (!addCommandInternal(LLCommandId(command_params), mToolbars[LLToolBarEnums::TOOLBAR_RIGHT]))
            {
                LL_WARNS() << "Error adding command '" << command_params.name() << "' to right toolbar." << LL_ENDL;
            }
        }
    }
    if (toolbar_set.bottom_toolbar.isProvided() && mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM])
    {
        if (toolbar_set.bottom_toolbar.button_display_mode.isProvided())
        {
            LLToolBarEnums::ButtonType button_type = toolbar_set.bottom_toolbar.button_display_mode;
            mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM]->setButtonType(button_type);
        }
        for (const LLCommandId::Params& command_params : toolbar_set.bottom_toolbar.commands)
        {
            if (!addCommandInternal(LLCommandId(command_params), mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM]))
            {
                LL_WARNS() << "Error adding command '" << command_params.name() << "' to bottom toolbar." << LL_ENDL;
            }
        }
    }

    // SL-18581: Don't show the starter avatar toolbar button for NUX users
    if (gAgent.isFirstLogin())
    {
        LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS));
        LL_WARNS() << "First login: checking for NUX user." << LL_ENDL;
        if (my_outfits_cat != NULL && my_outfits_cat->getDescendentCount() > 0)
        {
            LL_WARNS() << "First login: My Outfits folder is not empty, removing the avatar picker button." << LL_ENDL;
            for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
            {
                if (mToolbars[i])
                {
                    mToolbars[i]->removeCommand(LLCommandId("avatar"));
                }
            }
        }
    }

    mToolbarsLoaded = true;
    return true;
}

bool LLToolBarView::clearToolbars()
{
    for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        if (mToolbars[i])
        {
            mToolbars[i]->clearCommandsList();
        }
    }

    return true;
}

//static
bool LLToolBarView::loadDefaultToolbars()
{
    bool retval = false;

    if (gToolBarView)
    {
        retval = gToolBarView->loadToolbars(true);
        if (retval)
        {
            gToolBarView->saveToolbars();
        }
    }

    return retval;
}

//static
bool LLToolBarView::clearAllToolbars()
{
    bool retval = false;

    if (gToolBarView)
    {
        retval = gToolBarView->clearToolbars();
        if (retval)
        {
            gToolBarView->saveToolbars();
        }
    }

    return retval;
}

void LLToolBarView::saveToolbars() const
{
    if (!mToolbarsLoaded)
        return;

    // Build the parameter tree from the toolbar data
    LLToolBarView::ToolbarSet toolbar_set;
    if (mToolbars[LLToolBarEnums::TOOLBAR_LEFT])
    {
        toolbar_set.left_toolbar.button_display_mode = mToolbars[LLToolBarEnums::TOOLBAR_LEFT]->getButtonType();
        addToToolset(mToolbars[LLToolBarEnums::TOOLBAR_LEFT]->getCommandsList(), toolbar_set.left_toolbar);
    }
    if (mToolbars[LLToolBarEnums::TOOLBAR_RIGHT])
    {
        toolbar_set.right_toolbar.button_display_mode = mToolbars[LLToolBarEnums::TOOLBAR_RIGHT]->getButtonType();
        addToToolset(mToolbars[LLToolBarEnums::TOOLBAR_RIGHT]->getCommandsList(), toolbar_set.right_toolbar);
    }
    if (mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM])
    {
        toolbar_set.bottom_toolbar.button_display_mode = mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM]->getButtonType();
        addToToolset(mToolbars[LLToolBarEnums::TOOLBAR_BOTTOM]->getCommandsList(), toolbar_set.bottom_toolbar);
    }

    // Serialize the parameter tree
    LLXMLNodePtr output_node = new LLXMLNode("toolbars", false);
    LLXUIParser parser;
    parser.writeXUI(output_node, toolbar_set);

    // Write the resulting XML to file
    if(!output_node->isNull())
    {
        const std::string& filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "toolbars.xml");
        LLFILE *fp = LLFile::fopen(filename, "w");
        if (fp != NULL)
        {
            LLXMLNode::writeHeaderToFile(fp);
            output_node->writeToFile(fp);
            fclose(fp);
        }
    }
}

// Enumerate the commands in command_list and add them as Params to the toolbar
void LLToolBarView::addToToolset(command_id_list_t& command_list, Toolbar& toolbar) const
{
    LLCommandManager& mgr = LLCommandManager::instance();

    for (command_id_list_t::const_iterator it = command_list.begin();
         it != command_list.end();
         ++it)
    {
        LLCommand* command = mgr.getCommand(*it);
        if (command)
        {
            LLCommandId::Params command_name_param;
            command_name_param.name = command->name();
            toolbar.commands.add(command_name_param);
        }
    }
}

void LLToolBarView::onToolBarButtonAdded(LLView* button)
{
    llassert(button);

    if (button->getName() == "speak")
    {
        // Add the "Speak" button as a control view in LLTransientFloaterMgr
        // to prevent hiding the transient IM floater upon pressing "Speak".
        LLTransientFloaterMgr::getInstance()->addControlView(button);

        // Redock incoming and/or outgoing call windows, if applicable

        LLFloater* incoming_floater = LLFloaterReg::getLastFloaterInGroup("incoming_call");
        LLFloater* outgoing_floater = LLFloaterReg::getLastFloaterInGroup("outgoing_call");

        if (incoming_floater && incoming_floater->isShown())
        {
            LLCallDialog* incoming = dynamic_cast<LLCallDialog *>(incoming_floater);
            llassert(incoming);

            LLDockControl* dock_control = incoming->getDockControl();
            if (dock_control->getDock() == NULL)
            {
                incoming->dockToToolbarButton("speak");
            }
        }

        if (outgoing_floater && outgoing_floater->isShown())
        {
            LLCallDialog* outgoing = dynamic_cast<LLCallDialog *>(outgoing_floater);
            llassert(outgoing);

            LLDockControl* dock_control = outgoing->getDockControl();
            if (dock_control->getDock() == NULL)
            {
                outgoing->dockToToolbarButton("speak");
            }
        }
    }
    else if (button->getName() == "voice")
    {
        // Add the "Voice controls" button as a control view in LLTransientFloaterMgr
        // to prevent hiding the transient IM floater upon pressing "Voice controls".
        LLTransientFloaterMgr::getInstance()->addControlView(button);
    }
}

void LLToolBarView::onToolBarButtonRemoved(LLView* button)
{
    llassert(button);

    if (button->getName() == "speak")
    {
        LLTransientFloaterMgr::getInstance()->removeControlView(button);

        // Undock incoming and/or outgoing call windows

        LLFloater* incoming_floater = LLFloaterReg::getLastFloaterInGroup("incoming_call");
        LLFloater* outgoing_floater = LLFloaterReg::getLastFloaterInGroup("outgoing_call");

        if (incoming_floater && incoming_floater->isShown())
        {
            LLDockableFloater* incoming = dynamic_cast<LLDockableFloater *>(incoming_floater);
            llassert(incoming);

            LLDockControl* dock_control = incoming->getDockControl();
            dock_control->setDock(NULL);
        }

        if (outgoing_floater && outgoing_floater->isShown())
        {
            LLDockableFloater* outgoing = dynamic_cast<LLDockableFloater *>(outgoing_floater);
            llassert(outgoing);

            LLDockControl* dock_control = outgoing->getDockControl();
            dock_control->setDock(NULL);
        }
    }
    else if (button->getName() == "voice")
    {
        LLTransientFloaterMgr::getInstance()->removeControlView(button);
    }
}

void LLToolBarView::draw()
{
    LLRect toolbar_rects[LLToolBarEnums::TOOLBAR_COUNT];

    for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        if (mToolbars[i])
        {
            LLView::EOrientation orientation = LLToolBarEnums::getOrientation(mToolbars[i]->getSideType());

            if (orientation == LLLayoutStack::HORIZONTAL)
            {
                mToolbars[i]->getParent()->reshape(mToolbars[i]->getParent()->getRect().getWidth(), mToolbars[i]->getRect().getHeight());
            }
            else
            {
                mToolbars[i]->getParent()->reshape(mToolbars[i]->getRect().getWidth(), mToolbars[i]->getParent()->getRect().getHeight());
            }

            mToolbars[i]->localRectToOtherView(mToolbars[i]->getLocalRect(), &toolbar_rects[i], this);
        }
    }

    for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        mToolbars[i]->getParent()->setVisible(mShowToolbars
                                            && (mToolbars[i]->hasButtons()
                                            || isToolDragged()));
    }

    // Draw drop zones if drop of a tool is active
    if (isToolDragged())
    {
        static const LLUIColor drop_color = LLUIColorTable::instance().getColor( "ToolbarDropZoneColor" );

        for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
        {
            gl_rect_2d(toolbar_rects[i], drop_color, true);
        }
    }

    LLUICtrl::draw();
}


// ----------------------------------------
// Drag and Drop Handling
// ----------------------------------------


void LLToolBarView::startDragTool(S32 x, S32 y, LLToolBarButton* toolbarButton)
{
    resetDragTool(toolbarButton);

    // Flag the tool dragging but don't start it yet
    LLToolDragAndDrop::getInstance()->setDragStart( x, y );
}

bool LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type)
{
    if (LLToolDragAndDrop::getInstance()->isOverThreshold( x, y ))
    {
        if (!gToolBarView->mDragStarted)
        {
            // Start the tool dragging:

            // First, create the global drag and drop object
            std::vector<EDragAndDropType> types;
            uuid_vec_t cargo_ids;
            types.push_back(DAD_WIDGET);
            cargo_ids.push_back(uuid);
            LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_VIEWER;
            LLUUID srcID;
            LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src, srcID);

            // Second, stop the command if it is in progress and requires stopping!
            LLCommandId command_id = LLCommandId(uuid);
            gToolBarView->stopCommandInProgress(command_id);

            gToolBarView->mDragStarted = true;
            return true;
        }
        else
        {
            MASK mask = 0;
            return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
        }
    }
    return false;
}

bool LLToolBarView::handleDropTool( void* cargo_data, S32 x, S32 y, LLToolBar* toolbar)
{
    bool handled = false;
    LLInventoryObject* inv_item = static_cast<LLInventoryObject*>(cargo_data);

    LLAssetType::EType type = inv_item->getType();
    if (type == LLAssetType::AT_WIDGET)
    {
        handled = true;
        // Get the command from its uuid
        LLCommandManager& mgr = LLCommandManager::instance();
        LLCommandId command_id(inv_item->getUUID());
        LLCommand* command = mgr.getCommand(command_id);
        if (command)
        {
            // Suppress the command from the toolbars (including the one it's dropped in,
            // this will handle move position).
            S32 old_toolbar_loc = gToolBarView->hasCommand(command_id);
            LLToolBar* old_toolbar = NULL;

            if (old_toolbar_loc != LLToolBarEnums::TOOLBAR_NONE)
            {
                llassert(gToolBarView->mDragToolbarButton);
                old_toolbar = gToolBarView->mDragToolbarButton->getParentByType<LLToolBar>();
                if (old_toolbar->isReadOnly() && toolbar->isReadOnly())
                {
                    // do nothing
                }
                else
                {
                    int old_rank = LLToolBar::RANK_NONE;
                    gToolBarView->removeCommand(command_id, old_rank);
                }
            }

            // Convert the (x,y) position in rank in toolbar
            if (!toolbar->isReadOnly())
            {
                int new_rank = toolbar->getRankFromPosition(x,y);
                toolbar->addCommand(command_id, new_rank);
            }

            // Save the new toolbars configuration
            gToolBarView->saveToolbars();
        }
        else
        {
            LL_WARNS() << "Command couldn't be found in command manager" << LL_ENDL;
        }
    }

    resetDragTool(NULL);
    return handled;
}

void LLToolBarView::resetDragTool(LLToolBarButton* toolbarButton)
{
    // Clear the saved command, toolbar and rank
    gToolBarView->mDragStarted = false;
    gToolBarView->mDragToolbarButton = toolbarButton;
}

// Provide a handle on a free standing inventory item containing references to the tool.
// This might be used by Drag and Drop to move around references to tool items.
LLInventoryObject* LLToolBarView::getDragItem()
{
    if (mDragToolbarButton)
    {
        LLUUID item_uuid = mDragToolbarButton->getCommandId().uuid();
        mDragItem = new LLInventoryObject (item_uuid, LLUUID::null, LLAssetType::AT_WIDGET, "");
    }
    return mDragItem;
}

void LLToolBarView::setToolBarsVisible(bool visible)
{
    mShowToolbars = visible;
}

bool LLToolBarView::isModified() const
{
    bool modified = false;

    for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++)
    {
        modified |= mToolbars[i]->isModified();
    }

    return modified;
}