<commit_before>//
// Copyright (c) 2008-2014 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Precompiled.h"
#include "Console.h"
#include "Context.h"
#include "CoreEvents.h"
#include "DropDownList.h"
#include "EngineEvents.h"
#include "Font.h"
#include "Graphics.h"
#include "GraphicsEvents.h"
#include "Input.h"
#include "InputEvents.h"
#include "IOEvents.h"
#include "LineEdit.h"
#include "ListView.h"
#include "Log.h"
#include "ResourceCache.h"
#include "ScrollBar.h"
#include "Text.h"
#include "UI.h"
#include "UIEvents.h"

#include "DebugNew.h"

namespace Urho3D
{

static const int DEFAULT_CONSOLE_ROWS = 16;
static const int DEFAULT_HISTORY_SIZE = 16;

Console::Console(Context* context) :
    Object(context),
    autoVisibleOnError_(false),
    historyRows_(DEFAULT_HISTORY_SIZE),
    historyPosition_(0),
    printing_(false)
{
    UI* ui = GetSubsystem<UI>();
    UIElement* uiRoot = ui->GetRoot();

    // By default prevent the automatic showing of the screen keyboard
    focusOnShow_ = !ui->GetUseScreenKeyboard();

    background_ = uiRoot->CreateChild<BorderImage>();
    background_->SetBringToBack(false);
    background_->SetClipChildren(true);
    background_->SetEnabled(true);
    background_->SetVisible(false); // Hide by default
    background_->SetPriority(200); // Show on top of the debug HUD
    background_->SetBringToBack(false);
    background_->SetLayout(LM_VERTICAL);

    rowContainer_ = background_->CreateChild<ListView>();
    rowContainer_->SetHighlightMode(HM_ALWAYS);
    rowContainer_->SetMultiselect(true);

    commandLine_ = background_->CreateChild<UIElement>();
    commandLine_->SetLayoutMode(LM_HORIZONTAL);
    commandLine_->SetLayoutSpacing(1);
    interpreters_ = commandLine_->CreateChild<DropDownList>();
    lineEdit_ = commandLine_->CreateChild<LineEdit>();
    lineEdit_->SetFocusMode(FM_FOCUSABLE);  // Do not allow defocus with ESC

    closeButton_ = uiRoot->CreateChild<Button>();
    closeButton_->SetVisible(false);
    closeButton_->SetPriority(background_->GetPriority() + 1);  // Show on top of console's background
    closeButton_->SetBringToBack(false);

    SetNumRows(DEFAULT_CONSOLE_ROWS);

    SubscribeToEvent(interpreters_, E_ITEMSELECTED, HANDLER(Console, HandleInterpreterSelected));
    SubscribeToEvent(lineEdit_, E_TEXTFINISHED, HANDLER(Console, HandleTextFinished));
    SubscribeToEvent(lineEdit_, E_UNHANDLEDKEY, HANDLER(Console, HandleLineEditKey));
    SubscribeToEvent(closeButton_, E_RELEASED, HANDLER(Console, HandleCloseButtonPressed));
    SubscribeToEvent(E_SCREENMODE, HANDLER(Console, HandleScreenMode));
    SubscribeToEvent(E_LOGMESSAGE, HANDLER(Console, HandleLogMessage));
    SubscribeToEvent(E_POSTUPDATE, HANDLER(Console, HandlePostUpdate));
}

Console::~Console()
{
    background_->Remove();
    closeButton_->Remove();
}

void Console::SetDefaultStyle(XMLFile* style)
{
    if (!style)
        return;

    background_->SetDefaultStyle(style);
    background_->SetStyle("ConsoleBackground");
    rowContainer_->SetStyleAuto();
    for (unsigned i = 0; i < rowContainer_->GetNumItems(); ++i)
        rowContainer_->GetItem(i)->SetStyle("ConsoleText");
    interpreters_->SetStyleAuto();
    for (unsigned i = 0; i < interpreters_->GetNumItems(); ++i)
        interpreters_->GetItem(i)->SetStyle("ConsoleText");
    lineEdit_->SetStyle("ConsoleLineEdit");

    closeButton_->SetDefaultStyle(style);
    closeButton_->SetStyle("CloseButton");

    UpdateElements();
}

void Console::SetVisible(bool enable)
{
    Input* input = GetSubsystem<Input>();
    background_->SetVisible(enable);
    closeButton_->SetVisible(enable);
    if (enable)
    {
        // Check if we have receivers for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
        bool hasInterpreter = PopulateInterpreter();
        commandLine_->SetVisible(hasInterpreter);
        if (hasInterpreter && focusOnShow_)
            GetSubsystem<UI>()->SetFocusElement(lineEdit_);

        // Ensure the background has no empty space when shown without the lineedit
        background_->SetHeight(background_->GetMinHeight());

        // Show OS mouse
        savedMouseVisibility_ = input->IsMouseVisible();
        input->SetMouseVisible(true);
    }
    else
    {
        interpreters_->SetFocus(false);
        lineEdit_->SetFocus(false);

        // Restore OS mouse visibility
        input->SetMouseVisible(savedMouseVisibility_);
    }
}

void Console::Toggle()
{
    SetVisible(!IsVisible());
}

void Console::SetNumBufferedRows(unsigned rows)
{
    if (rows < displayedRows_)
        return;

    rowContainer_->DisableLayoutUpdate();

    int delta = rowContainer_->GetNumItems() - rows;
    if (delta > 0)
    {
        // We have more, remove oldest rows first
        for (int i = 0; i < delta; ++i)
            rowContainer_->RemoveItem((unsigned)0);
    }
    else
    {
        // We have less, add more rows at the top
        for (int i = 0; i > delta; --i)
        {
            Text* text = new Text(context_);
            // If style is already set, apply here to ensure proper height of the console when
            // amount of rows is changed
            if (background_->GetDefaultStyle())
                text->SetStyle("ConsoleText");
            rowContainer_->InsertItem(0, text);
        }
    }

    rowContainer_->EnsureItemVisibility(rowContainer_->GetItem(rowContainer_->GetNumItems() - 1));
    rowContainer_->EnableLayoutUpdate();
    rowContainer_->UpdateLayout();

    UpdateElements();
}

void Console::SetNumRows(unsigned rows)
{
    if (!rows)
        return;

    displayedRows_ = rows;
    if (GetNumBufferedRows() < rows)
        SetNumBufferedRows(rows);

    UpdateElements();
}

void Console::SetNumHistoryRows(unsigned rows)
{
    historyRows_ = rows;
    if (history_.Size() > rows)
        history_.Resize(rows);
    if (historyPosition_ > rows)
        historyPosition_ = rows;
}

void Console::SetFocusOnShow(bool enable)
{
    focusOnShow_ = enable;
}

void Console::UpdateElements()
{
    int width = GetSubsystem<Graphics>()->GetWidth();
    const IntRect& border = background_->GetLayoutBorder();
    const IntRect& panelBorder = rowContainer_->GetScrollPanel()->GetClipBorder();
    rowContainer_->SetFixedWidth(width - border.left_ - border.right_);
    rowContainer_->SetFixedHeight(displayedRows_ * rowContainer_->GetItem((unsigned)0)->GetHeight() + panelBorder.top_ + panelBorder.bottom_ +
        (rowContainer_->GetHorizontalScrollBar()->IsVisible() ? rowContainer_->GetHorizontalScrollBar()->GetHeight() : 0));
    background_->SetFixedWidth(width);
    background_->SetHeight(background_->GetMinHeight());
}

XMLFile* Console::GetDefaultStyle() const
{
    return background_->GetDefaultStyle(false);
}

bool Console::IsVisible() const
{
    return background_ && background_->IsVisible();
}

unsigned Console::GetNumBufferedRows() const
{
    return rowContainer_->GetNumItems();
}

void Console::CopySelectedRows() const
{
    rowContainer_->CopySelectedItemsToClipboard();
}

const String& Console::GetHistoryRow(unsigned index) const
{
    return index < history_.Size() ? history_[index] : String::EMPTY;
}

bool Console::PopulateInterpreter()
{
    interpreters_->RemoveAllItems();

    HashSet<Object*>* receivers = context_->GetEventReceivers(E_CONSOLECOMMAND);
    if (!receivers || receivers->Empty())
        return false;

    Vector<String> names;
    for (HashSet<Object*>::ConstIterator iter = receivers->Begin(); iter != receivers->End(); ++iter)
        names.Push((*iter)->GetTypeName());
    Sort(names.Begin(), names.End());

    unsigned selection = M_MAX_UNSIGNED;
    for (unsigned i = 0; i < names.Size(); ++i)
    {
        const String& name = names[i];
        if (name == commandInterpreter_)
            selection = i;
        Text* text = new Text(context_);
        text->SetStyle("ConsoleText");
        text->SetText(name);
        interpreters_->AddItem(text);
    }

    const IntRect& border = interpreters_->GetPopup()->GetLayoutBorder();
    interpreters_->SetMaxWidth(interpreters_->GetListView()->GetContentElement()->GetWidth() + border.left_ + border.right_);
    bool enabled = interpreters_->GetNumItems() > 1;
    interpreters_->SetEnabled(enabled);
    interpreters_->SetFocusMode(enabled ? FM_FOCUSABLE_DEFOCUSABLE : FM_NOTFOCUSABLE);

    if (selection == M_MAX_UNSIGNED)
    {
        selection = 0;
        commandInterpreter_ = names[selection];
    }
    interpreters_->SetSelection(selection);

    return true;
}

void Console::HandleInterpreterSelected(StringHash eventType, VariantMap& eventData)
{
    commandInterpreter_ = static_cast<Text*>(interpreters_->GetSelectedItem())->GetText();
    lineEdit_->SetFocus(true);
}

void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
{
    using namespace TextFinished;

    String line = lineEdit_->GetText();
    if (!line.Empty())
    {
        // Send the command as an event for script subsystem
        using namespace ConsoleCommand;

        VariantMap& eventData = GetEventDataMap();
        eventData[P_COMMAND] = line;
        eventData[P_ID] = static_cast<Text*>(interpreters_->GetSelectedItem())->GetText();
        SendEvent(E_CONSOLECOMMAND, eventData);

        // Store to history, then clear the lineedit
        history_.Push(line);
        if (history_.Size() > historyRows_)
            history_.Erase(history_.Begin());
        historyPosition_ = history_.Size();

        currentRow_.Clear();
        lineEdit_->SetText(currentRow_);
    }
}

void Console::HandleLineEditKey(StringHash eventType, VariantMap& eventData)
{
    if (!historyRows_)
        return;

    using namespace UnhandledKey;

    bool changed = false;

    switch (eventData[P_KEY].GetInt())
    {
    case KEY_UP:
        if (historyPosition_ > 0)
        {
            if (historyPosition_ == history_.Size())
                currentRow_ = lineEdit_->GetText();
            --historyPosition_;
            changed = true;
        }
        break;

    case KEY_DOWN:
        if (historyPosition_ < history_.Size())
        {
            ++historyPosition_;
            changed = true;
        }
        break;
    }

    if (changed)
    {
        if (historyPosition_ < history_.Size())
            lineEdit_->SetText(history_[historyPosition_]);
        else
            lineEdit_->SetText(currentRow_);
    }
}

void Console::HandleCloseButtonPressed(StringHash eventType, VariantMap& eventData)
{
    SetVisible(false);
}

void Console::HandleScreenMode(StringHash eventType, VariantMap& eventData)
{
    UpdateElements();
}

void Console::HandleLogMessage(StringHash eventType, VariantMap& eventData)
{
    // If printing a log message causes more messages to be logged (error accessing font), disregard them
    if (printing_)
        return;

    using namespace LogMessage;

    int level = eventData[P_LEVEL].GetInt();
    // The message may be multi-line, so split to rows in that case
    Vector<String> rows = eventData[P_MESSAGE].GetString().Split('\n');

    for (unsigned i = 0; i < rows.Size(); ++i)
        pendingRows_.Push(MakePair(level, rows[i]));

    if (autoVisibleOnError_ && level == LOG_ERROR && !IsVisible())
        SetVisible(true);
}

void Console::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
{
    if (!rowContainer_->GetNumItems() || pendingRows_.Empty())
        return;

    printing_ = true;
    rowContainer_->DisableLayoutUpdate();

    Text* text;
    for (unsigned i = 0; i < pendingRows_.Size(); ++i)
    {
        rowContainer_->RemoveItem((unsigned)0);
        text = new Text(context_);
        text->SetText(pendingRows_[i].second_);
        // Make error message highlight
        text->SetStyle(pendingRows_[i].first_ == LOG_ERROR ? "ConsoleHighlightedText" : "ConsoleText");
        rowContainer_->AddItem(text);
    }

    pendingRows_.Clear();

    rowContainer_->EnsureItemVisibility(text);
    rowContainer_->EnableLayoutUpdate();
    rowContainer_->UpdateLayout();
    UpdateElements();   // May need to readjust the height due to scrollbar visibility changes
    printing_ = false;
}

}
<commit_msg>Fix invisible console still gaining the input focus bug.<commit_after>//
// Copyright (c) 2008-2014 the Urho3D project.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

#include "Precompiled.h"
#include "Console.h"
#include "Context.h"
#include "CoreEvents.h"
#include "DropDownList.h"
#include "EngineEvents.h"
#include "Font.h"
#include "Graphics.h"
#include "GraphicsEvents.h"
#include "Input.h"
#include "InputEvents.h"
#include "IOEvents.h"
#include "LineEdit.h"
#include "ListView.h"
#include "Log.h"
#include "ResourceCache.h"
#include "ScrollBar.h"
#include "Text.h"
#include "UI.h"
#include "UIEvents.h"

#include "DebugNew.h"

namespace Urho3D
{

static const int DEFAULT_CONSOLE_ROWS = 16;
static const int DEFAULT_HISTORY_SIZE = 16;

Console::Console(Context* context) :
    Object(context),
    autoVisibleOnError_(false),
    historyRows_(DEFAULT_HISTORY_SIZE),
    historyPosition_(0),
    printing_(false)
{
    UI* ui = GetSubsystem<UI>();
    UIElement* uiRoot = ui->GetRoot();

    // By default prevent the automatic showing of the screen keyboard
    focusOnShow_ = !ui->GetUseScreenKeyboard();

    background_ = uiRoot->CreateChild<BorderImage>();
    background_->SetBringToBack(false);
    background_->SetClipChildren(true);
    background_->SetEnabled(true);
    background_->SetVisible(false); // Hide by default
    background_->SetPriority(200); // Show on top of the debug HUD
    background_->SetBringToBack(false);
    background_->SetLayout(LM_VERTICAL);

    rowContainer_ = background_->CreateChild<ListView>();
    rowContainer_->SetHighlightMode(HM_ALWAYS);
    rowContainer_->SetMultiselect(true);

    commandLine_ = background_->CreateChild<UIElement>();
    commandLine_->SetLayoutMode(LM_HORIZONTAL);
    commandLine_->SetLayoutSpacing(1);
    interpreters_ = commandLine_->CreateChild<DropDownList>();
    lineEdit_ = commandLine_->CreateChild<LineEdit>();
    lineEdit_->SetFocusMode(FM_FOCUSABLE);  // Do not allow defocus with ESC

    closeButton_ = uiRoot->CreateChild<Button>();
    closeButton_->SetVisible(false);
    closeButton_->SetPriority(background_->GetPriority() + 1);  // Show on top of console's background
    closeButton_->SetBringToBack(false);

    SetNumRows(DEFAULT_CONSOLE_ROWS);

    SubscribeToEvent(interpreters_, E_ITEMSELECTED, HANDLER(Console, HandleInterpreterSelected));
    SubscribeToEvent(lineEdit_, E_TEXTFINISHED, HANDLER(Console, HandleTextFinished));
    SubscribeToEvent(lineEdit_, E_UNHANDLEDKEY, HANDLER(Console, HandleLineEditKey));
    SubscribeToEvent(closeButton_, E_RELEASED, HANDLER(Console, HandleCloseButtonPressed));
    SubscribeToEvent(E_SCREENMODE, HANDLER(Console, HandleScreenMode));
    SubscribeToEvent(E_LOGMESSAGE, HANDLER(Console, HandleLogMessage));
    SubscribeToEvent(E_POSTUPDATE, HANDLER(Console, HandlePostUpdate));
}

Console::~Console()
{
    background_->Remove();
    closeButton_->Remove();
}

void Console::SetDefaultStyle(XMLFile* style)
{
    if (!style)
        return;

    background_->SetDefaultStyle(style);
    background_->SetStyle("ConsoleBackground");
    rowContainer_->SetStyleAuto();
    for (unsigned i = 0; i < rowContainer_->GetNumItems(); ++i)
        rowContainer_->GetItem(i)->SetStyle("ConsoleText");
    interpreters_->SetStyleAuto();
    for (unsigned i = 0; i < interpreters_->GetNumItems(); ++i)
        interpreters_->GetItem(i)->SetStyle("ConsoleText");
    lineEdit_->SetStyle("ConsoleLineEdit");

    closeButton_->SetDefaultStyle(style);
    closeButton_->SetStyle("CloseButton");

    UpdateElements();
}

void Console::SetVisible(bool enable)
{
    Input* input = GetSubsystem<Input>();
    background_->SetVisible(enable);
    closeButton_->SetVisible(enable);
    if (enable)
    {
        // Check if we have receivers for E_CONSOLECOMMAND every time here in case the handler is being added later dynamically
        bool hasInterpreter = PopulateInterpreter();
        commandLine_->SetVisible(hasInterpreter);
        if (hasInterpreter && focusOnShow_)
            GetSubsystem<UI>()->SetFocusElement(lineEdit_);

        // Ensure the background has no empty space when shown without the lineedit
        background_->SetHeight(background_->GetMinHeight());

        // Show OS mouse
        savedMouseVisibility_ = input->IsMouseVisible();
        input->SetMouseVisible(true);
    }
    else
    {
        rowContainer_->SetFocus(false);
        interpreters_->SetFocus(false);
        lineEdit_->SetFocus(false);

        // Restore OS mouse visibility
        input->SetMouseVisible(savedMouseVisibility_);
    }
}

void Console::Toggle()
{
    SetVisible(!IsVisible());
}

void Console::SetNumBufferedRows(unsigned rows)
{
    if (rows < displayedRows_)
        return;

    rowContainer_->DisableLayoutUpdate();

    int delta = rowContainer_->GetNumItems() - rows;
    if (delta > 0)
    {
        // We have more, remove oldest rows first
        for (int i = 0; i < delta; ++i)
            rowContainer_->RemoveItem((unsigned)0);
    }
    else
    {
        // We have less, add more rows at the top
        for (int i = 0; i > delta; --i)
        {
            Text* text = new Text(context_);
            // If style is already set, apply here to ensure proper height of the console when
            // amount of rows is changed
            if (background_->GetDefaultStyle())
                text->SetStyle("ConsoleText");
            rowContainer_->InsertItem(0, text);
        }
    }

    rowContainer_->EnsureItemVisibility(rowContainer_->GetItem(rowContainer_->GetNumItems() - 1));
    rowContainer_->EnableLayoutUpdate();
    rowContainer_->UpdateLayout();

    UpdateElements();
}

void Console::SetNumRows(unsigned rows)
{
    if (!rows)
        return;

    displayedRows_ = rows;
    if (GetNumBufferedRows() < rows)
        SetNumBufferedRows(rows);

    UpdateElements();
}

void Console::SetNumHistoryRows(unsigned rows)
{
    historyRows_ = rows;
    if (history_.Size() > rows)
        history_.Resize(rows);
    if (historyPosition_ > rows)
        historyPosition_ = rows;
}

void Console::SetFocusOnShow(bool enable)
{
    focusOnShow_ = enable;
}

void Console::UpdateElements()
{
    int width = GetSubsystem<Graphics>()->GetWidth();
    const IntRect& border = background_->GetLayoutBorder();
    const IntRect& panelBorder = rowContainer_->GetScrollPanel()->GetClipBorder();
    rowContainer_->SetFixedWidth(width - border.left_ - border.right_);
    rowContainer_->SetFixedHeight(displayedRows_ * rowContainer_->GetItem((unsigned)0)->GetHeight() + panelBorder.top_ + panelBorder.bottom_ +
        (rowContainer_->GetHorizontalScrollBar()->IsVisible() ? rowContainer_->GetHorizontalScrollBar()->GetHeight() : 0));
    background_->SetFixedWidth(width);
    background_->SetHeight(background_->GetMinHeight());
}

XMLFile* Console::GetDefaultStyle() const
{
    return background_->GetDefaultStyle(false);
}

bool Console::IsVisible() const
{
    return background_ && background_->IsVisible();
}

unsigned Console::GetNumBufferedRows() const
{
    return rowContainer_->GetNumItems();
}

void Console::CopySelectedRows() const
{
    rowContainer_->CopySelectedItemsToClipboard();
}

const String& Console::GetHistoryRow(unsigned index) const
{
    return index < history_.Size() ? history_[index] : String::EMPTY;
}

bool Console::PopulateInterpreter()
{
    interpreters_->RemoveAllItems();

    HashSet<Object*>* receivers = context_->GetEventReceivers(E_CONSOLECOMMAND);
    if (!receivers || receivers->Empty())
        return false;

    Vector<String> names;
    for (HashSet<Object*>::ConstIterator iter = receivers->Begin(); iter != receivers->End(); ++iter)
        names.Push((*iter)->GetTypeName());
    Sort(names.Begin(), names.End());

    unsigned selection = M_MAX_UNSIGNED;
    for (unsigned i = 0; i < names.Size(); ++i)
    {
        const String& name = names[i];
        if (name == commandInterpreter_)
            selection = i;
        Text* text = new Text(context_);
        text->SetStyle("ConsoleText");
        text->SetText(name);
        interpreters_->AddItem(text);
    }

    const IntRect& border = interpreters_->GetPopup()->GetLayoutBorder();
    interpreters_->SetMaxWidth(interpreters_->GetListView()->GetContentElement()->GetWidth() + border.left_ + border.right_);
    bool enabled = interpreters_->GetNumItems() > 1;
    interpreters_->SetEnabled(enabled);
    interpreters_->SetFocusMode(enabled ? FM_FOCUSABLE_DEFOCUSABLE : FM_NOTFOCUSABLE);

    if (selection == M_MAX_UNSIGNED)
    {
        selection = 0;
        commandInterpreter_ = names[selection];
    }
    interpreters_->SetSelection(selection);

    return true;
}

void Console::HandleInterpreterSelected(StringHash eventType, VariantMap& eventData)
{
    commandInterpreter_ = static_cast<Text*>(interpreters_->GetSelectedItem())->GetText();
    lineEdit_->SetFocus(true);
}

void Console::HandleTextFinished(StringHash eventType, VariantMap& eventData)
{
    using namespace TextFinished;

    String line = lineEdit_->GetText();
    if (!line.Empty())
    {
        // Send the command as an event for script subsystem
        using namespace ConsoleCommand;

        VariantMap& eventData = GetEventDataMap();
        eventData[P_COMMAND] = line;
        eventData[P_ID] = static_cast<Text*>(interpreters_->GetSelectedItem())->GetText();
        SendEvent(E_CONSOLECOMMAND, eventData);

        // Store to history, then clear the lineedit
        history_.Push(line);
        if (history_.Size() > historyRows_)
            history_.Erase(history_.Begin());
        historyPosition_ = history_.Size();

        currentRow_.Clear();
        lineEdit_->SetText(currentRow_);
    }
}

void Console::HandleLineEditKey(StringHash eventType, VariantMap& eventData)
{
    if (!historyRows_)
        return;

    using namespace UnhandledKey;

    bool changed = false;

    switch (eventData[P_KEY].GetInt())
    {
    case KEY_UP:
        if (historyPosition_ > 0)
        {
            if (historyPosition_ == history_.Size())
                currentRow_ = lineEdit_->GetText();
            --historyPosition_;
            changed = true;
        }
        break;

    case KEY_DOWN:
        if (historyPosition_ < history_.Size())
        {
            ++historyPosition_;
            changed = true;
        }
        break;
    }

    if (changed)
    {
        if (historyPosition_ < history_.Size())
            lineEdit_->SetText(history_[historyPosition_]);
        else
            lineEdit_->SetText(currentRow_);
    }
}

void Console::HandleCloseButtonPressed(StringHash eventType, VariantMap& eventData)
{
    SetVisible(false);
}

void Console::HandleScreenMode(StringHash eventType, VariantMap& eventData)
{
    UpdateElements();
}

void Console::HandleLogMessage(StringHash eventType, VariantMap& eventData)
{
    // If printing a log message causes more messages to be logged (error accessing font), disregard them
    if (printing_)
        return;

    using namespace LogMessage;

    int level = eventData[P_LEVEL].GetInt();
    // The message may be multi-line, so split to rows in that case
    Vector<String> rows = eventData[P_MESSAGE].GetString().Split('\n');

    for (unsigned i = 0; i < rows.Size(); ++i)
        pendingRows_.Push(MakePair(level, rows[i]));

    if (autoVisibleOnError_ && level == LOG_ERROR && !IsVisible())
        SetVisible(true);
}

void Console::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
{
    if (!rowContainer_->GetNumItems() || pendingRows_.Empty())
        return;

    printing_ = true;
    rowContainer_->DisableLayoutUpdate();

    Text* text;
    for (unsigned i = 0; i < pendingRows_.Size(); ++i)
    {
        rowContainer_->RemoveItem((unsigned)0);
        text = new Text(context_);
        text->SetText(pendingRows_[i].second_);
        // Make error message highlight
        text->SetStyle(pendingRows_[i].first_ == LOG_ERROR ? "ConsoleHighlightedText" : "ConsoleText");
        rowContainer_->AddItem(text);
    }

    pendingRows_.Clear();

    rowContainer_->EnsureItemVisibility(text);
    rowContainer_->EnableLayoutUpdate();
    rowContainer_->UpdateLayout();
    UpdateElements();   // May need to readjust the height due to scrollbar visibility changes
    printing_ = false;
}

}
<|endoftext|>


<commit_before>#include "testing/testing.hpp"

#include "map/framework.hpp"

#include "platform/http_request.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/platform_tests_support/write_dir_changer.hpp"

#include "coding/file_name_utils.hpp"
#include "coding/internal/file_data.hpp"

#include "storage/storage.hpp"

#include "std/unique_ptr.hpp"

using namespace platform;
using namespace storage;

namespace
{

string const kTestWebServer = "http://new-search.mapswithme.com/";

string const kMapTestDir = "map-tests";

string const kCountriesTxtFile = COUNTRIES_MIGRATE_FILE;

string const kMwmVersion1 = "160126";
size_t const kCountriesTxtFileSize1 = 131201;

string const kMwmVersion2 = "160128";
size_t const kCountriesTxtFileSize2 = 127870;

string const kGroupCountryId = "Belarus";

bool DownloadFile(string const & url,
                  string const & filePath,
                  size_t fileSize)
{
  using namespace downloader;

  HttpRequest::StatusT httpStatus;
  bool finished = false;

  unique_ptr<HttpRequest> request(HttpRequest::GetFile({url}, filePath, fileSize,
                                  [&](HttpRequest & request)
  {
    HttpRequest::StatusT const s = request.Status();
    if (s == HttpRequest::EFailed || s == HttpRequest::ECompleted)
    {
      httpStatus = s;
      finished = true;
      testing::StopEventLoop();
    }
  }));

  testing::RunEventLoop();

  return httpStatus == HttpRequest::ECompleted;
}

string GetCountriesTxtWebUrl(string const version)
{
  return kTestWebServer + "/direct/" + version + "/" + kCountriesTxtFile;
}

string GetCountriesTxtFilePath()
{
  return my::JoinFoldersToPath(GetPlatform().WritableDir(), kCountriesTxtFile);
}

string GetMwmFilePath(string const & version, TCountryId const & countryId)
{
  return my::JoinFoldersToPath({GetPlatform().WritableDir(), version},
                               countryId + DATA_FILE_EXTENSION);
}

} // namespace

UNIT_TEST(SmallMwms_Update_Test)
{
  WritableDirChanger writableDirChanger(kMapTestDir);

  Platform & platform = GetPlatform();

  auto onProgressFn = [&](TCountryId const & countryId, TLocalAndRemoteSize const & mapSize) {};

  // Download countries.txt for version 1
  TEST(DownloadFile(GetCountriesTxtWebUrl(kMwmVersion1), GetCountriesTxtFilePath(), kCountriesTxtFileSize1), ());

  {
    Framework f;
    auto & storage = f.Storage();
    string const version = strings::to_string(storage.GetCurrentDataVersion());
    TEST(version::IsSingleMwm(storage.GetCurrentDataVersion()), ());
    TEST_EQUAL(version, kMwmVersion1, ());
    auto onChangeCountryFn = [&](TCountryId const & countryId)
    {
      if (!storage.IsDownloadInProgress())
        testing::StopEventLoop();
    };
    storage.Subscribe(onChangeCountryFn, onProgressFn);
    storage.SetDownloadingUrlsForTesting({kTestWebServer});

    TCountriesVec children;
    storage.GetChildren(kGroupCountryId, children);

    // Download group
    TEST(storage.DownloadNode(kGroupCountryId), ());
    testing::RunEventLoop();

    // Check group node status is EOnDisk
    NodeAttrs attrs;
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());

    // Check mwm files for version 1 are present
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }
  }

  // Replace countries.txt by version 2
  TEST(my::DeleteFileX(GetCountriesTxtFilePath()), ());
  TEST(DownloadFile(GetCountriesTxtWebUrl(kMwmVersion2), GetCountriesTxtFilePath(), kCountriesTxtFileSize2), ());

  {
    Framework f;
    auto & storage = f.Storage();
    string const version = strings::to_string(storage.GetCurrentDataVersion());
    TEST(version::IsSingleMwm(storage.GetCurrentDataVersion()), ());
    TEST_EQUAL(version, kMwmVersion2, ());
    auto onChangeCountryFn = [&](TCountryId const & countryId)
    {
      if (!storage.IsDownloadInProgress())
        testing::StopEventLoop();
    };
    storage.Subscribe(onChangeCountryFn, onProgressFn);
    storage.SetDownloadingUrlsForTesting({kTestWebServer});

    TCountriesVec children;
    storage.GetChildren(kGroupCountryId, children);

    // Check group node status is EOnDiskOutOfDate
    NodeAttrs attrs;
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDiskOutOfDate, attrs.m_status, ());

    // Check children node status is EOnDiskOutOfDate
    for (auto const & child : children)
    {
      NodeAttrs attrs;
      storage.GetNodeAttrs(child, attrs);
      TEST_EQUAL(NodeStatus::OnDiskOutOfDate, attrs.m_status, ());
    }

    // Check mwm files for version 1 are present
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }

    // Download group, new version
    storage.DownloadNode(kGroupCountryId);
    testing::RunEventLoop();

    // Check group node status is EOnDisk
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());

    // Check children node status is EOnDisk
    for (auto const & child : children)
    {
      NodeAttrs attrs;
      storage.GetNodeAttrs(child, attrs);
      TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());
    }

    // Check mwm files for version 2 are present and not present for version 1
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      string const mwmFullPathV2 = GetMwmFilePath(kMwmVersion2, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV2), ());
      TEST(!platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }
  }
}
<commit_msg>Fix compile error<commit_after>#include "testing/testing.hpp"

#include "map/framework.hpp"

#include "platform/http_request.hpp"
#include "platform/local_country_file_utils.hpp"
#include "platform/platform.hpp"
#include "platform/platform_tests_support/write_dir_changer.hpp"

#include "coding/file_name_utils.hpp"
#include "coding/internal/file_data.hpp"

#include "storage/storage.hpp"

#include "std/unique_ptr.hpp"

using namespace platform;
using namespace storage;

namespace
{

string const kTestWebServer = "http://new-search.mapswithme.com/";

string const kMapTestDir = "map-tests";

string const kCountriesTxtFile = COUNTRIES_MIGRATE_FILE;

string const kMwmVersion1 = "160126";
size_t const kCountriesTxtFileSize1 = 131201;

string const kMwmVersion2 = "160128";
size_t const kCountriesTxtFileSize2 = 127870;

string const kGroupCountryId = "Belarus";

bool DownloadFile(string const & url,
                  string const & filePath,
                  size_t fileSize)
{
  using namespace downloader;

  HttpRequest::StatusT httpStatus;
  bool finished = false;

  unique_ptr<HttpRequest> request(HttpRequest::GetFile({url}, filePath, fileSize,
                                  [&](HttpRequest & request)
  {
    HttpRequest::StatusT const s = request.Status();
    if (s == HttpRequest::EFailed || s == HttpRequest::ECompleted)
    {
      httpStatus = s;
      finished = true;
      testing::StopEventLoop();
    }
  }));

  testing::RunEventLoop();

  return httpStatus == HttpRequest::ECompleted;
}

string GetCountriesTxtWebUrl(string const version)
{
  return kTestWebServer + "/direct/" + version + "/" + kCountriesTxtFile;
}

string GetCountriesTxtFilePath()
{
  return my::JoinFoldersToPath(GetPlatform().WritableDir(), kCountriesTxtFile);
}

string GetMwmFilePath(string const & version, TCountryId const & countryId)
{
  return my::JoinFoldersToPath({GetPlatform().WritableDir(), version},
                               countryId + DATA_FILE_EXTENSION);
}

} // namespace

UNIT_TEST(SmallMwms_Update_Test)
{
  WritableDirChanger writableDirChanger(kMapTestDir);

  Platform & platform = GetPlatform();

  auto onProgressFn = [&](TCountryId const & countryId, TLocalAndRemoteSize const & mapSize) {};

  // Download countries.txt for version 1
  TEST(DownloadFile(GetCountriesTxtWebUrl(kMwmVersion1), GetCountriesTxtFilePath(), kCountriesTxtFileSize1), ());

  {
    Framework f;
    auto & storage = f.Storage();
    string const version = strings::to_string(storage.GetCurrentDataVersion());
    TEST(version::IsSingleMwm(storage.GetCurrentDataVersion()), ());
    TEST_EQUAL(version, kMwmVersion1, ());
    auto onChangeCountryFn = [&](TCountryId const & countryId)
    {
      if (!storage.IsDownloadInProgress())
        testing::StopEventLoop();
    };
    storage.Subscribe(onChangeCountryFn, onProgressFn);
    storage.SetDownloadingUrlsForTesting({kTestWebServer});

    TCountriesVec children;
    storage.GetChildren(kGroupCountryId, children);

    // Download group
    storage.DownloadNode(kGroupCountryId);
    testing::RunEventLoop();

    // Check group node status is EOnDisk
    NodeAttrs attrs;
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());

    // Check mwm files for version 1 are present
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }
  }

  // Replace countries.txt by version 2
  TEST(my::DeleteFileX(GetCountriesTxtFilePath()), ());
  TEST(DownloadFile(GetCountriesTxtWebUrl(kMwmVersion2), GetCountriesTxtFilePath(), kCountriesTxtFileSize2), ());

  {
    Framework f;
    auto & storage = f.Storage();
    string const version = strings::to_string(storage.GetCurrentDataVersion());
    TEST(version::IsSingleMwm(storage.GetCurrentDataVersion()), ());
    TEST_EQUAL(version, kMwmVersion2, ());
    auto onChangeCountryFn = [&](TCountryId const & countryId)
    {
      if (!storage.IsDownloadInProgress())
        testing::StopEventLoop();
    };
    storage.Subscribe(onChangeCountryFn, onProgressFn);
    storage.SetDownloadingUrlsForTesting({kTestWebServer});

    TCountriesVec children;
    storage.GetChildren(kGroupCountryId, children);

    // Check group node status is EOnDiskOutOfDate
    NodeAttrs attrs;
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDiskOutOfDate, attrs.m_status, ());

    // Check children node status is EOnDiskOutOfDate
    for (auto const & child : children)
    {
      NodeAttrs attrs;
      storage.GetNodeAttrs(child, attrs);
      TEST_EQUAL(NodeStatus::OnDiskOutOfDate, attrs.m_status, ());
    }

    // Check mwm files for version 1 are present
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }

    // Download group, new version
    storage.DownloadNode(kGroupCountryId);
    testing::RunEventLoop();

    // Check group node status is EOnDisk
    storage.GetNodeAttrs(kGroupCountryId, attrs);
    TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());

    // Check children node status is EOnDisk
    for (auto const & child : children)
    {
      NodeAttrs attrs;
      storage.GetNodeAttrs(child, attrs);
      TEST_EQUAL(NodeStatus::OnDisk, attrs.m_status, ());
    }

    // Check mwm files for version 2 are present and not present for version 1
    for (auto const & child : children)
    {
      string const mwmFullPathV1 = GetMwmFilePath(kMwmVersion1, child);
      string const mwmFullPathV2 = GetMwmFilePath(kMwmVersion2, child);
      TEST(platform.IsFileExistsByFullPath(mwmFullPathV2), ());
      TEST(!platform.IsFileExistsByFullPath(mwmFullPathV1), ());
    }
  }
}
<|endoftext|>


<commit_before>// Module:  Log4CPLUS
// File:    loggerimpl.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.1  2003/04/03 01:44:01  tcsmith
// Renamed from categoryimpl.cxx
//

#include <log4cplus/spi/loggerimpl.h>
#include <log4cplus/appender.h>
#include <log4cplus/hierarchy.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/spi/rootlogger.h>
#include <cassert>
#include <stdexcept>

using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

//////////////////////////////////////////////////////////////////////////////
// Logger Constructors and Destructor
//////////////////////////////////////////////////////////////////////////////
LoggerImpl::LoggerImpl(const log4cplus::tstring& name, Hierarchy& h)
  : name(name),
    ll(NOT_SET_LOG_LEVEL),
    parent(NULL),
    additive(true),
    hierarchy(h)
{
}

LoggerImpl::~LoggerImpl()
{
    getLogLog().debug(LOG4CPLUS_TEXT("Destroying Logger: ") + name);
}

//////////////////////////////////////////////////////////////////////////////
// Logger Methods
//////////////////////////////////////////////////////////////////////////////

void
LoggerImpl::callAppenders(const InternalLoggingEvent& event)
{
    int writes = 0;
    for(const LoggerImpl* c = this; c != NULL; c=c->parent.get()) {
        writes += c->appendLoopOnAppenders(event);
        if(!c->additive) {
            break;
        }
    }

    // No appenders in hierarchy, warn user only once.
    if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
        getLogLog().error(  LOG4CPLUS_TEXT("No appenders could be found for logger (")
			  + getName()
			  + LOG4CPLUS_TEXT(")."));
        getLogLog().error(LOG4CPLUS_TEXT("Please initialize the log4cplus system properly."));
        hierarchy.emittedNoAppenderWarning = true;
    }
}

void
LoggerImpl::closeNestedAppenders()
{
    SharedAppenderPtrList appenders = getAllAppenders();
    for(SharedAppenderPtrList::iterator it=appenders.begin(); it!=appenders.end(); ++it)
    {
        (*it)->close();
    }
}

bool
LoggerImpl::isEnabledFor(LogLevel ll) const
{
    if(hierarchy.disableValue >= ll) {
        return false;
    }
    return ll >= getChainedLogLevel();
}

void
LoggerImpl::log(LogLevel ll,
                const log4cplus::tstring& message,
                const char* file,
                int line)
{
    if(isEnabledFor(ll)) {
        forcedLog(ll, message, file, line);
    }
}

LogLevel
LoggerImpl::getChainedLogLevel() const
{
    for(const LoggerImpl *c=this; c != NULL; c=c->parent.get()) {
        if(c == NULL) {
            getLogLog().error(LOG4CPLUS_TEXT("LoggerImpl::getChainedLogLevel()- " \
				             "Internal error: NullPointer"));
            helpers::throwNullPointerException(__FILE__, __LINE__);
        }
        if(c->ll != NOT_SET_LOG_LEVEL) {
            return c->ll;
        }
    }

    getLogLog().error(LOG4CPLUS_TEXT("LoggerImpl::getChainedLogLevel()- No valid " \
			             "LogLevel found"));
    throw std::runtime_error(LOG4CPLUS_TEXT("No valid LogLevel found"));
}

Hierarchy&
LoggerImpl::getHierarchy() const
{
    return hierarchy;
}

bool
LoggerImpl::getAdditivity() const
{
    return additive;
}

void
LoggerImpl::setAdditivity(bool additive)
{
    this->additive = additive;
}

void
LoggerImpl::forcedLog(LogLevel ll,
                      const log4cplus::tstring& message,
                      const char* file,
                      int line)
{
    callAppenders(spi::InternalLoggingEvent(this->getName(), ll, message, file, line));
}

<commit_msg>Fixed UNICODE support.<commit_after>// Module:  Log4CPLUS
// File:    loggerimpl.cxx
// Created: 6/2001
// Author:  Tad E. Smith
//
//
// Copyright (C) Tad E. Smith  All rights reserved.
//
// This software is published under the terms of the Apache Software
// License version 1.1, a copy of which has been included with this
// distribution in the LICENSE.APL file.
//
// $Log: not supported by cvs2svn $
// Revision 1.2  2003/04/18 21:26:16  tcsmith
// Converted from std::string to log4cplus::tstring.
//
// Revision 1.1  2003/04/03 01:44:01  tcsmith
// Renamed from categoryimpl.cxx
//

#include <log4cplus/spi/loggerimpl.h>
#include <log4cplus/appender.h>
#include <log4cplus/hierarchy.h>
#include <log4cplus/helpers/loglog.h>
#include <log4cplus/spi/loggingevent.h>
#include <log4cplus/spi/rootlogger.h>
#include <cassert>
#include <stdexcept>

using namespace log4cplus;
using namespace log4cplus::helpers;
using namespace log4cplus::spi;

//////////////////////////////////////////////////////////////////////////////
// Logger Constructors and Destructor
//////////////////////////////////////////////////////////////////////////////
LoggerImpl::LoggerImpl(const log4cplus::tstring& name, Hierarchy& h)
  : name(name),
    ll(NOT_SET_LOG_LEVEL),
    parent(NULL),
    additive(true),
    hierarchy(h)
{
}

LoggerImpl::~LoggerImpl()
{
    getLogLog().debug(LOG4CPLUS_TEXT("Destroying Logger: ") + name);
}

//////////////////////////////////////////////////////////////////////////////
// Logger Methods
//////////////////////////////////////////////////////////////////////////////

void
LoggerImpl::callAppenders(const InternalLoggingEvent& event)
{
    int writes = 0;
    for(const LoggerImpl* c = this; c != NULL; c=c->parent.get()) {
        writes += c->appendLoopOnAppenders(event);
        if(!c->additive) {
            break;
        }
    }

    // No appenders in hierarchy, warn user only once.
    if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
        getLogLog().error(  LOG4CPLUS_TEXT("No appenders could be found for logger (")
			  + getName()
			  + LOG4CPLUS_TEXT(")."));
        getLogLog().error(LOG4CPLUS_TEXT("Please initialize the log4cplus system properly."));
        hierarchy.emittedNoAppenderWarning = true;
    }
}

void
LoggerImpl::closeNestedAppenders()
{
    SharedAppenderPtrList appenders = getAllAppenders();
    for(SharedAppenderPtrList::iterator it=appenders.begin(); it!=appenders.end(); ++it)
    {
        (*it)->close();
    }
}

bool
LoggerImpl::isEnabledFor(LogLevel ll) const
{
    if(hierarchy.disableValue >= ll) {
        return false;
    }
    return ll >= getChainedLogLevel();
}

void
LoggerImpl::log(LogLevel ll,
                const log4cplus::tstring& message,
                const char* file,
                int line)
{
    if(isEnabledFor(ll)) {
        forcedLog(ll, message, file, line);
    }
}

LogLevel
LoggerImpl::getChainedLogLevel() const
{
    for(const LoggerImpl *c=this; c != NULL; c=c->parent.get()) {
        if(c == NULL) {
            getLogLog().error(LOG4CPLUS_TEXT("LoggerImpl::getChainedLogLevel()- Internal error: NullPointer"));
            helpers::throwNullPointerException(__FILE__, __LINE__);
        }
        if(c->ll != NOT_SET_LOG_LEVEL) {
            return c->ll;
        }
    }

    getLogLog().error( LOG4CPLUS_TEXT("LoggerImpl::getChainedLogLevel()- No valid LogLevel found") );
    throw std::runtime_error("No valid LogLevel found");
}

Hierarchy&
LoggerImpl::getHierarchy() const
{
    return hierarchy;
}

bool
LoggerImpl::getAdditivity() const
{
    return additive;
}

void
LoggerImpl::setAdditivity(bool additive)
{
    this->additive = additive;
}

void
LoggerImpl::forcedLog(LogLevel ll,
                      const log4cplus::tstring& message,
                      const char* file,
                      int line)
{
    callAppenders(spi::InternalLoggingEvent(this->getName(), ll, message, file, line));
}

<|endoftext|>


<commit_before>/***********************************************************************
 *    filename:   Element.cpp
 *    created:    28/10/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/Element.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

BOOST_AUTO_TEST_SUITE(Element)

BOOST_AUTO_TEST_CASE(RelativeSizing)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::percent(), 25.0f * CEGUI::UDim::percent()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100.0f, 100.0f));
    BOOST_CHECK_EQUAL(child->getPixelSize(), CEGUI::Sizef(50.0f, 25.0f));

    CEGUI::Element* innerChild = new CEGUI::Element();
    child->addChild(innerChild);
    innerChild->setSize(CEGUI::USize(200.0f * CEGUI::UDim::percent(), 100.0f * CEGUI::UDim::percent()));
    BOOST_CHECK_EQUAL(innerChild->getPixelSize(), CEGUI::Sizef(100.0f, 25.0f));

    delete innerChild;
    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(RelativePositioning)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setPosition(CEGUI::UVector2(50.0f * CEGUI::UDim::percent(), 50.0f * CEGUI::UDim::percent()));
    child->setSize(CEGUI::USize(10.0f * CEGUI::UDim::px(), 10 * CEGUI::UDim::px()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50.0f, 50.0f, 60.0f, 60.0f));

    delete child;
    delete root;
}

// TODO: RelativeRotation!

BOOST_AUTO_TEST_CASE(HorizontalLeftAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    BOOST_CHECK_EQUAL(child->getHorizontalAlignment(), CEGUI::HA_LEFT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 50, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(10, 0, 60, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(25, 0, 75, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(35, 0, 85, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalRightAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_RIGHT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50, 0, 100, 0));

    child->setPosition(CEGUI::UVector2(-10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(40, 0, 90, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalTopAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    BOOST_CHECK_EQUAL(child->getVerticalAlignment(), CEGUI::VA_TOP);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 50));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 5, 0, 55));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 25, 0, 75));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 30, 0, 80));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalBottomAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_BOTTOM);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 50, 0, 100));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), -5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 45, 0, 95));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(AspectLocking)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getAspectMode(), CEGUI::AM_IGNORE);
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100, 100));

    root->setAspectMode(CEGUI::AM_SHRINK);
    root->setAspectRatio(1.0f / 2.0f);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(50, 100));

    root->setAspectMode(CEGUI::AM_EXPAND);
    root->setAspectRatio(1.0f / 2.0f);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100, 200));

    delete root;
}

BOOST_AUTO_TEST_CASE(PixelAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setPosition(CEGUI::UVector2(0.2f * CEGUI::UDim::px(), 0.2f * CEGUI::UDim::px()));
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100.0f * CEGUI::UDim::px()));

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK(root->isPixelAligned());

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 100));

    root->setPixelAligned(false);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0.2f, 0.2f, 100.2f, 100.2f));

    delete root;
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Added test case for min/max size in Element<commit_after>/***********************************************************************
 *    filename:   Element.cpp
 *    created:    28/10/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/Element.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

BOOST_AUTO_TEST_SUITE(Element)

BOOST_AUTO_TEST_CASE(RelativeSizing)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::percent(), 25.0f * CEGUI::UDim::percent()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100.0f, 100.0f));
    BOOST_CHECK_EQUAL(child->getPixelSize(), CEGUI::Sizef(50.0f, 25.0f));

    CEGUI::Element* innerChild = new CEGUI::Element();
    child->addChild(innerChild);
    innerChild->setSize(CEGUI::USize(200.0f * CEGUI::UDim::percent(), 100.0f * CEGUI::UDim::percent()));
    BOOST_CHECK_EQUAL(innerChild->getPixelSize(), CEGUI::Sizef(100.0f, 25.0f));

    delete innerChild;
    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(RelativePositioning)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setPosition(CEGUI::UVector2(50.0f * CEGUI::UDim::percent(), 50.0f * CEGUI::UDim::percent()));
    child->setSize(CEGUI::USize(10.0f * CEGUI::UDim::px(), 10 * CEGUI::UDim::px()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50.0f, 50.0f, 60.0f, 60.0f));

    delete child;
    delete root;
}

// TODO: RelativeRotation!

BOOST_AUTO_TEST_CASE(MinMaxSize)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    root->setMaxSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 50 * CEGUI::UDim::px()));;

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(50.0f, 50.0f));

    root->setMaxSize(CEGUI::USize(75.0f * CEGUI::UDim::px(), 75.0f * CEGUI::UDim::px()));;

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(75.0f, 75.0f));

    root->setMaxSize(CEGUI::USize(1000.0f * CEGUI::UDim::px(), 1000 * CEGUI::UDim::px()));;

    root->setMinSize(CEGUI::USize(125.0f * CEGUI::UDim::px(), 125.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(125.0f, 125.0f));

    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalLeftAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    BOOST_CHECK_EQUAL(child->getHorizontalAlignment(), CEGUI::HA_LEFT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 50, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(10, 0, 60, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(25, 0, 75, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(35, 0, 85, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalRightAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_RIGHT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50, 0, 100, 0));

    child->setPosition(CEGUI::UVector2(-10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(40, 0, 90, 0));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalTopAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    BOOST_CHECK_EQUAL(child->getVerticalAlignment(), CEGUI::VA_TOP);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 50));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 5, 0, 55));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 25, 0, 75));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 30, 0, 80));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(VerticalBottomAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_BOTTOM);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 50, 0, 100));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), -5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 45, 0, 95));

    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(AspectLocking)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getAspectMode(), CEGUI::AM_IGNORE);
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100, 100));

    root->setAspectMode(CEGUI::AM_SHRINK);
    root->setAspectRatio(1.0f / 2.0f);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(50, 100));

    root->setAspectMode(CEGUI::AM_EXPAND);
    root->setAspectRatio(1.0f / 2.0f);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100, 200));

    delete root;
}

BOOST_AUTO_TEST_CASE(PixelAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setPosition(CEGUI::UVector2(0.2f * CEGUI::UDim::px(), 0.2f * CEGUI::UDim::px()));
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100.0f * CEGUI::UDim::px()));

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK(root->isPixelAligned());

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 100));

    root->setPixelAligned(false);

    // todo: should have tolerances or something, or does boost do that automatically?
    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0.2f, 0.2f, 100.2f, 100.2f));

    delete root;
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>//
// Custom Casts
//
namespace {
$(when measurements $(foreach measurements
$(if active and ( custom_cast or label_map ) then
OUT=[[
template<typename FilterType>
struct ${name}CustomCast
{
  template <typename T>
]]
if custom_cast then
OUT=OUT..[[
  static ${type} Helper( const T & value ) { return ${custom_cast}; }
]]
end
OUT=OUT..[[

  static ${type} CustomCast( const FilterType *f]]
if parameters then
  for inum=1,#parameters do
    OUT=OUT..', '..parameters[inum].type..' '..parameters[inum].name
  end
end
OUT=OUT..[[ )
  {
    return ]]
if custom_cast then
  OUT=OUT..[[${name}CustomCast::Helper(]]
end
if label_map then
  OUT=OUT..[[f->GetOutput()->GetLabelObject(label)->Get${name}()]]
else
  OUT=OUT..[[f->Get${name}(label)]]
end
if custom_cast then
  OUT=OUT..')'
end
OUT=OUT..';'..[[

  }
};
]]
  end)))
}
<commit_msg>fix custom cast template component<commit_after>//
// Custom Casts
//
namespace {
$(when measurements $(foreach measurements
$(if active and ( custom_cast or label_map ) then
OUT=[[
template<typename FilterType>
struct ${name}CustomCast
{
]]
if custom_cast then
OUT=OUT..[[
  template <typename T>
  static ${type} Helper( const T & value ) { return ${custom_cast}; }
]]
end
OUT=OUT..[[

  static ${type} CustomCast( const FilterType *f]]
if parameters then
  for inum=1,#parameters do
    OUT=OUT..', '..parameters[inum].type..' '..parameters[inum].name
  end
end
OUT=OUT..[[ )
  {
    return ]]
if custom_cast then
  OUT=OUT..[[${name}CustomCast::Helper(]]
end
if label_map then
  OUT=OUT..[[f->GetOutput()->GetLabelObject(label)->Get${name}()]]
else
  OUT=OUT..[[f->Get${name}(label)]]
end
if custom_cast then
  OUT=OUT..')'
end
OUT=OUT..';'..[[

  }
};
]]
  end)))
}
<|endoftext|>


<commit_before><commit_msg>Use the full URL of the icon in the notification, not just the string passed in -- so that that string doesn't have to be absolute.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/extensions/file_browser_event_router.h"

#include "base/json/json_writer.h"
#include "base/memory/singleton.h"
#include "base/stl_util-inl.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/notifications/system_notification.h"
#include "chrome/browser/extensions/extension_event_names.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/profiles/profile.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

ExtensionFileBrowserEventRouter::ExtensionFileBrowserEventRouter()
    : profile_(NULL) {
}

ExtensionFileBrowserEventRouter::~ExtensionFileBrowserEventRouter() {
}

void ExtensionFileBrowserEventRouter::ObserveFileSystemEvents(
    Profile* profile) {
  if (profile_)
    return;
  profile_ = profile;
  if (chromeos::UserManager::Get()->user_is_logged_in()) {
    chromeos::MountLibrary* lib =
        chromeos::CrosLibrary::Get()->GetMountLibrary();
    lib->AddObserver(this);
    lib->RequestMountInfoRefresh();
  }
}

void ExtensionFileBrowserEventRouter::StopObservingFileSystemEvents() {
  if (!profile_)
    return;
  chromeos::MountLibrary* lib =
      chromeos::CrosLibrary::Get()->GetMountLibrary();
  lib->RemoveObserver(this);
  profile_ = NULL;
}

// static
ExtensionFileBrowserEventRouter*
    ExtensionFileBrowserEventRouter::GetInstance() {
  return Singleton<ExtensionFileBrowserEventRouter>::get();
}

void ExtensionFileBrowserEventRouter::DiskChanged(
    chromeos::MountLibraryEventType event,
    const chromeos::MountLibrary::Disk* disk) {
  if (event == chromeos::MOUNT_DISK_ADDED) {
    OnDiskAdded(disk);
  } else if (event == chromeos::MOUNT_DISK_REMOVED) {
    OnDiskRemoved(disk);
  } else if (event == chromeos::MOUNT_DISK_CHANGED) {
    OnDiskChanged(disk);
  }
}

void ExtensionFileBrowserEventRouter::DeviceChanged(
    chromeos::MountLibraryEventType event,
    const std::string& device_path) {
  if (event == chromeos::MOUNT_DEVICE_ADDED) {
    OnDeviceAdded(device_path);
  } else if (event == chromeos::MOUNT_DEVICE_REMOVED) {
    OnDeviceRemoved(device_path);
  } else if (event == chromeos::MOUNT_DEVICE_SCANNED) {
    OnDeviceScanned(device_path);
  }
}

void ExtensionFileBrowserEventRouter::DispatchEvent(
    const std::string& web_path) {
  if (!profile_) {
    NOTREACHED();
    return;
  }

  ListValue args;
  args.Append(Value::CreateStringValue(web_path));
  std::string args_json;
  base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
  profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
      extension_event_names::kOnFileBrowserDiskChanged, args_json, NULL,
      GURL());
}

void ExtensionFileBrowserEventRouter::OnDiskAdded(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk added: " << disk->device_path();
  if (disk->device_path().empty()) {
    VLOG(1) << "Empty system path for " << disk->device_path();
    return;
  }
  if (disk->is_parent()) {
    if (!disk->has_media())
      HideDeviceNotification(disk->system_path());
    return;
  }

  // If disk is not mounted yet, give it a try.
  if (disk->mount_path().empty()) {
    // Initiate disk mount operation.
    chromeos::MountLibrary* lib =
        chromeos::CrosLibrary::Get()->GetMountLibrary();
    lib->MountPath(disk->device_path().c_str());
  }
}

void ExtensionFileBrowserEventRouter::OnDiskRemoved(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk removed: " << disk->device_path();
  HideDeviceNotification(disk->system_path());
  MountPointMap::iterator iter = mounted_devices_.find(disk->device_path());
  if (iter == mounted_devices_.end())
    return;

  chromeos::MountLibrary* lib =
      chromeos::CrosLibrary::Get()->GetMountLibrary();
  // TODO(zelidrag): This for some reason does not work as advertized.
  // we might need to clean up mount directory on FILE thread here as well.
  lib->UnmountPath(disk->device_path().c_str());

  DispatchEvent(iter->second);
  mounted_devices_.erase(iter);
}

void ExtensionFileBrowserEventRouter::OnDiskChanged(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk changed : " << disk->device_path();
  if (!disk->mount_path().empty()) {
    HideDeviceNotification(disk->system_path());
    // Remember this mount point.
    if (mounted_devices_.find(disk->device_path()) == mounted_devices_.end()) {
      mounted_devices_.insert(
          std::pair<std::string, std::string>(disk->device_path(),
                                              disk->mount_path()));
      DispatchEvent(disk->mount_path());
      // TODO(zelidrag): Find better icon here.
      ShowDeviceNotification(disk->system_path(), IDR_PAGEINFO_INFO,
          l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_MOUNTED_MESSAGE));
    }
  }
}

void ExtensionFileBrowserEventRouter::OnDeviceAdded(
    const std::string& device_path) {
  VLOG(1) << "Device added : " << device_path;
  // TODO(zelidrag): Find better icon here.
  ShowDeviceNotification(device_path, IDR_PAGEINFO_INFO,
      l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE));

}

void ExtensionFileBrowserEventRouter::OnDeviceRemoved(
    const std::string& system_path) {
}

void ExtensionFileBrowserEventRouter::OnDeviceScanned(
    const std::string& device_path) {
  VLOG(1) << "Device scanned : " << device_path;
}

void ExtensionFileBrowserEventRouter::ShowDeviceNotification(
    const std::string& system_path, int icon_resource_id,
    const string16& message) {
  NotificationMap::iterator iter = FindNotificationForPath(system_path);
  std::string mount_path;
  if (iter != notifications_.end()) {
    iter->second->Show(message, false, false);
  } else {
    if (!profile_) {
      NOTREACHED();
      return;
    }
    chromeos::SystemNotification* notification =
        new chromeos::SystemNotification(
            profile_,
            system_path,
            icon_resource_id,
            l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_DETECTION_TITLE));
    notifications_.insert(NotificationMap::value_type(system_path,
        linked_ptr<chromeos::SystemNotification>(notification)));
    notification->Show(message, false, false);
  }
}

void ExtensionFileBrowserEventRouter::HideDeviceNotification(
    const std::string& system_path) {
  NotificationMap::iterator iter = FindNotificationForPath(system_path);
  if (iter != notifications_.end()) {
    iter->second->Hide();
    notifications_.erase(iter);
  }
}

ExtensionFileBrowserEventRouter::NotificationMap::iterator
    ExtensionFileBrowserEventRouter::FindNotificationForPath(
        const std::string& system_path) {
  for (NotificationMap::iterator iter = notifications_.begin();
       iter != notifications_.end();
       ++iter) {
    const std::string& notification_device_path = iter->first;
    // Doing a sub string match so that we find if this new one is a subdevice
    // of another already inserted device.
    if (StartsWithASCII(system_path, notification_device_path, true)) {
      return iter;
    }
  }
  return notifications_.end();
}
<commit_msg>Hiding device notifications for devices that have been removed<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/extensions/file_browser_event_router.h"

#include "base/json/json_writer.h"
#include "base/memory/singleton.h"
#include "base/stl_util-inl.h"
#include "base/values.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/notifications/system_notification.h"
#include "chrome/browser/extensions/extension_event_names.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/profiles/profile.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"

ExtensionFileBrowserEventRouter::ExtensionFileBrowserEventRouter()
    : profile_(NULL) {
}

ExtensionFileBrowserEventRouter::~ExtensionFileBrowserEventRouter() {
}

void ExtensionFileBrowserEventRouter::ObserveFileSystemEvents(
    Profile* profile) {
  if (profile_)
    return;
  profile_ = profile;
  if (chromeos::UserManager::Get()->user_is_logged_in()) {
    chromeos::MountLibrary* lib =
        chromeos::CrosLibrary::Get()->GetMountLibrary();
    lib->AddObserver(this);
    lib->RequestMountInfoRefresh();
  }
}

void ExtensionFileBrowserEventRouter::StopObservingFileSystemEvents() {
  if (!profile_)
    return;
  chromeos::MountLibrary* lib =
      chromeos::CrosLibrary::Get()->GetMountLibrary();
  lib->RemoveObserver(this);
  profile_ = NULL;
}

// static
ExtensionFileBrowserEventRouter*
    ExtensionFileBrowserEventRouter::GetInstance() {
  return Singleton<ExtensionFileBrowserEventRouter>::get();
}

void ExtensionFileBrowserEventRouter::DiskChanged(
    chromeos::MountLibraryEventType event,
    const chromeos::MountLibrary::Disk* disk) {
  if (event == chromeos::MOUNT_DISK_ADDED) {
    OnDiskAdded(disk);
  } else if (event == chromeos::MOUNT_DISK_REMOVED) {
    OnDiskRemoved(disk);
  } else if (event == chromeos::MOUNT_DISK_CHANGED) {
    OnDiskChanged(disk);
  }
}

void ExtensionFileBrowserEventRouter::DeviceChanged(
    chromeos::MountLibraryEventType event,
    const std::string& device_path) {
  if (event == chromeos::MOUNT_DEVICE_ADDED) {
    OnDeviceAdded(device_path);
  } else if (event == chromeos::MOUNT_DEVICE_REMOVED) {
    OnDeviceRemoved(device_path);
  } else if (event == chromeos::MOUNT_DEVICE_SCANNED) {
    OnDeviceScanned(device_path);
  }
}

void ExtensionFileBrowserEventRouter::DispatchEvent(
    const std::string& web_path) {
  if (!profile_) {
    NOTREACHED();
    return;
  }

  ListValue args;
  args.Append(Value::CreateStringValue(web_path));
  std::string args_json;
  base::JSONWriter::Write(&args, false /* pretty_print */, &args_json);
  profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
      extension_event_names::kOnFileBrowserDiskChanged, args_json, NULL,
      GURL());
}

void ExtensionFileBrowserEventRouter::OnDiskAdded(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk added: " << disk->device_path();
  if (disk->device_path().empty()) {
    VLOG(1) << "Empty system path for " << disk->device_path();
    return;
  }
  if (disk->is_parent()) {
    if (!disk->has_media())
      HideDeviceNotification(disk->system_path());
    return;
  }

  // If disk is not mounted yet, give it a try.
  if (disk->mount_path().empty()) {
    // Initiate disk mount operation.
    chromeos::MountLibrary* lib =
        chromeos::CrosLibrary::Get()->GetMountLibrary();
    lib->MountPath(disk->device_path().c_str());
  }
}

void ExtensionFileBrowserEventRouter::OnDiskRemoved(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk removed: " << disk->device_path();
  HideDeviceNotification(disk->system_path());
  MountPointMap::iterator iter = mounted_devices_.find(disk->device_path());
  if (iter == mounted_devices_.end())
    return;

  chromeos::MountLibrary* lib =
      chromeos::CrosLibrary::Get()->GetMountLibrary();
  // TODO(zelidrag): This for some reason does not work as advertized.
  // we might need to clean up mount directory on FILE thread here as well.
  lib->UnmountPath(disk->device_path().c_str());

  DispatchEvent(iter->second);
  mounted_devices_.erase(iter);
}

void ExtensionFileBrowserEventRouter::OnDiskChanged(
    const chromeos::MountLibrary::Disk* disk) {
  VLOG(1) << "Disk changed : " << disk->device_path();
  if (!disk->mount_path().empty()) {
    HideDeviceNotification(disk->system_path());
    // Remember this mount point.
    if (mounted_devices_.find(disk->device_path()) == mounted_devices_.end()) {
      mounted_devices_.insert(
          std::pair<std::string, std::string>(disk->device_path(),
                                              disk->mount_path()));
      DispatchEvent(disk->mount_path());
      // TODO(zelidrag): Find better icon here.
      ShowDeviceNotification(disk->system_path(), IDR_PAGEINFO_INFO,
          l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_MOUNTED_MESSAGE));
    }
  }
}

void ExtensionFileBrowserEventRouter::OnDeviceAdded(
    const std::string& device_path) {
  VLOG(1) << "Device added : " << device_path;
  // TODO(zelidrag): Find better icon here.
  ShowDeviceNotification(device_path, IDR_PAGEINFO_INFO,
      l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_SCANNING_MESSAGE));

}

void ExtensionFileBrowserEventRouter::OnDeviceRemoved(
    const std::string& system_path) {
  HideDeviceNotification(system_path);
}

void ExtensionFileBrowserEventRouter::OnDeviceScanned(
    const std::string& device_path) {
  VLOG(1) << "Device scanned : " << device_path;
}

void ExtensionFileBrowserEventRouter::ShowDeviceNotification(
    const std::string& system_path, int icon_resource_id,
    const string16& message) {
  NotificationMap::iterator iter = FindNotificationForPath(system_path);
  std::string mount_path;
  if (iter != notifications_.end()) {
    iter->second->Show(message, false, false);
  } else {
    if (!profile_) {
      NOTREACHED();
      return;
    }
    chromeos::SystemNotification* notification =
        new chromeos::SystemNotification(
            profile_,
            system_path,
            icon_resource_id,
            l10n_util::GetStringUTF16(IDS_REMOVABLE_DEVICE_DETECTION_TITLE));
    notifications_.insert(NotificationMap::value_type(system_path,
        linked_ptr<chromeos::SystemNotification>(notification)));
    notification->Show(message, false, false);
  }
}

void ExtensionFileBrowserEventRouter::HideDeviceNotification(
    const std::string& system_path) {
  NotificationMap::iterator iter = FindNotificationForPath(system_path);
  if (iter != notifications_.end()) {
    iter->second->Hide();
    notifications_.erase(iter);
  }
}

ExtensionFileBrowserEventRouter::NotificationMap::iterator
    ExtensionFileBrowserEventRouter::FindNotificationForPath(
        const std::string& system_path) {
  for (NotificationMap::iterator iter = notifications_.begin();
       iter != notifications_.end();
       ++iter) {
    const std::string& notification_device_path = iter->first;
    // Doing a sub string match so that we find if this new one is a subdevice
    // of another already inserted device.
    if (StartsWithASCII(system_path, notification_device_path, true)) {
      return iter;
    }
  }
  return notifications_.end();
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_power_library.h"
#include "chrome/browser/chromeos/frame/browser_view.h"
#include "chrome/browser/chromeos/status/browser_status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
#include "grit/theme_resources.h"

namespace chromeos {
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;

class PowerMenuButtonTest : public CrosInProcessBrowserTest {
 protected:
  PowerMenuButtonTest() : CrosInProcessBrowserTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    SetStatusAreaMocksExpectations();
  }

  PowerMenuButton* GetPowerMenuButton() {
    BrowserView* view = static_cast<BrowserView*>(browser()->window());
    PowerMenuButton* power = static_cast<BrowserStatusAreaView*>(view->
        GetViewByID(VIEW_ID_STATUS_AREA))->power_view();
    return power;
  }

  int CallPowerChangedAndGetIconId() {
    PowerMenuButton* power = GetPowerMenuButton();
    power->PowerChanged(mock_power_library_);
    return power->icon_id();
  }
};

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(false)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));

  // Test the 12 battery charging states.
  int id = IDR_STATUSBAR_BATTERY_CHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryDischargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(false)));

  // Test the 12 battery discharing states.
  int id = IDR_STATUSBAR_BATTERY_DISCHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

}  // namespace chromeos
<commit_msg>Mark failing tests with FAIL_<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/status/power_menu_button.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h"
#include "chrome/browser/chromeos/cros/mock_power_library.h"
#include "chrome/browser/chromeos/frame/browser_view.h"
#include "chrome/browser/chromeos/status/browser_status_area_view.h"
#include "chrome/browser/chromeos/view_ids.h"
#include "grit/theme_resources.h"

namespace chromeos {
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;

class PowerMenuButtonTest : public CrosInProcessBrowserTest {
 protected:
  PowerMenuButtonTest() : CrosInProcessBrowserTest() {}

  virtual void SetUpInProcessBrowserTestFixture() {
    InitStatusAreaMocks();
    SetStatusAreaMocksExpectations();
  }

  PowerMenuButton* GetPowerMenuButton() {
    BrowserView* view = static_cast<BrowserView*>(browser()->window());
    PowerMenuButton* power = static_cast<BrowserStatusAreaView*>(view->
        GetViewByID(VIEW_ID_STATUS_AREA))->power_view();
    return power;
  }

  int CallPowerChangedAndGetIconId() {
    PowerMenuButton* power = GetPowerMenuButton();
    power->PowerChanged(mock_power_library_);
    return power->icon_id();
  }
};

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryMissingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(false)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_MISSING, CallPowerChangedAndGetIconId());
}

IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, BatteryChargedTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));
  EXPECT_EQ(IDR_STATUSBAR_BATTERY_CHARGED, CallPowerChangedAndGetIconId());
}

// http://crbug.com/48912
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, FAIL_BatteryChargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(true)));

  // Test the 12 battery charging states.
  int id = IDR_STATUSBAR_BATTERY_CHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

// http://crbug.com/48912
IN_PROC_BROWSER_TEST_F(PowerMenuButtonTest, FAIL_BatteryDischargingTest) {
  EXPECT_CALL(*mock_power_library_, battery_is_present())
      .WillRepeatedly((Return(true)));
  EXPECT_CALL(*mock_power_library_, battery_fully_charged())
      .WillRepeatedly((Return(false)));
  EXPECT_CALL(*mock_power_library_, line_power_on())
      .WillRepeatedly((Return(false)));

  // Test the 12 battery discharing states.
  int id = IDR_STATUSBAR_BATTERY_DISCHARGING_1;
  for (float precent = 6.0; precent < 100.0; precent += 8.0) {
    EXPECT_CALL(*mock_power_library_, battery_percentage())
        .WillRepeatedly((Return(precent)));
    EXPECT_EQ(id, CallPowerChangedAndGetIconId());
    id++;
  }
}

}  // namespace chromeos
<|endoftext|>