<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: global.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 04:09:44 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _RTL_OSTRINGBUFFER_HXX_
#include <rtl/strbuf.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef     _OSL_THREAD_H_
#include    <osl/thread.h>
#endif
#ifndef     _OSL_FILE_HXX_
#include    <osl/file.hxx>
#endif

#include <stdlib.h>
#include <stdio.h>
#if defined(SAL_W32) || defined(SAL_OS2)
#include <io.h>
#include <direct.h>
#include <errno.h>
#endif

#ifdef UNX
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#endif

#ifndef _CODEMAKER_GLOBAL_HXX_
#include    <codemaker/global.hxx>
#endif

#ifdef SAL_UNX
#define SEPARATOR '/'
#else
#define SEPARATOR '\\'
#endif

using namespace ::rtl;
using namespace ::osl;

OString createFileNameFromType( const OString& destination,
                                const OString typeName,
                                const OString postfix,
                                sal_Bool bLowerCase,
                                const OString prefix )
{
    OString type(typeName);

    if (bLowerCase)
    {
        type = typeName.toAsciiLowerCase();
    }

    sal_uInt32 length = destination.getLength();

    sal_Bool withPoint = sal_False;
    if (length == 0)
    {
        length++;
        withPoint = sal_True;
    }

    length += prefix.getLength() + type.getLength() + postfix.getLength();

    sal_Bool withSeperator = sal_False;
    if (destination.getStr()[destination.getLength()] != '\\' &&
        destination.getStr()[destination.getLength()] != '/' &&
        type.getStr()[0] != '\\' &&
        type.getStr()[0] != '/')
    {
        length++;
        withSeperator = sal_True;
    }

    OStringBuffer nameBuffer(length);

    if (withPoint)
        nameBuffer.append('.');
    else
        nameBuffer.append(destination.getStr(), destination.getLength());

    if (withSeperator)
        nameBuffer.append("/", 1);

    OString tmpStr(type);
    if (prefix.getLength() > 0)
    {
        tmpStr = type.replaceAt(type.lastIndexOf('/')+1, 0, prefix);
    }

    nameBuffer.append(tmpStr.getStr(), tmpStr.getLength());
    nameBuffer.append(postfix.getStr(), postfix.getLength());

    OString fileName(nameBuffer);

    sal_Char token;
#ifdef SAL_UNX
    fileName = fileName.replace('\\', '/');
    token = '/';
#else
    fileName = fileName.replace('/', '\\');
    token = '\\';
#endif

    nameBuffer = OStringBuffer(length);

    sal_Int32 nIndex = 0;
    do
    {
        nameBuffer.append(fileName.getToken( 0, token, nIndex ).getStr());

        if (nameBuffer.getLength() == 0 || OString(".") == nameBuffer.getStr())
        {
            nameBuffer.append(token);
            continue;
        }

#ifdef SAL_UNX
        if (mkdir((char*)nameBuffer.getStr(), 0777) == -1)
#else
           if (mkdir((char*)nameBuffer.getStr()) == -1)
#endif
        {
            if ( errno == ENOENT )
                return OString();
        }

        nameBuffer.append(token);
    }
    while ( nIndex >= 0 );

    return fileName;
}

sal_Bool fileExists(const OString& fileName)
{
    FILE  *f= fopen(fileName.getStr(), "r");

    if (f != NULL)
    {
        fclose(f);
        return sal_True;
    }

    return sal_False;
}

sal_Bool checkFileContent(const OString& targetFileName, const OString& tmpFileName)
{
    FILE  *target = fopen(targetFileName.getStr(), "r");
    FILE  *tmp = fopen(tmpFileName.getStr(), "r");
    sal_Bool ret = sal_False;

    if (target != NULL && tmp != NULL)
    {
        sal_Bool    bFindChanges = sal_False;
        sal_Char    buffer1[1024+1];
        sal_Char    buffer2[1024+1];
        sal_Int32   n1 = 0;
        sal_Int32   n2 = 0;

        while ( !bFindChanges && !feof(target) && !feof(tmp))
        {
            n1 = fread(buffer1, sizeof(sal_Char), 1024, target);
            n2 = fread(buffer2, sizeof(sal_Char), 1024, tmp);

            if ( n1 != n2 )
            {
                bFindChanges = sal_True;
            }
            else
            {
                if ( rtl_compareMemory(buffer1, buffer2, n2) != 0 )
                    bFindChanges =  sal_True;
            }
        }

        fclose(target);
        fclose(tmp);

        if ( bFindChanges )
        {
            if ( !unlink(targetFileName.getStr()) )
                if ( !rename(tmpFileName.getStr(), targetFileName.getStr()) )
                    ret = sal_True;
        }
        else
        {
            if ( !unlink(tmpFileName.getStr()) )
                ret = sal_True;
        }
    }

    return ret;
}

const OString inGlobalSet(const OUString & rValue)
{
    OString sValue( OUStringToOString(rValue, RTL_TEXTENCODING_UTF8) );
    static StringSet aGlobalMap;
    StringSet::iterator iter = aGlobalMap.find( sValue );
    if( iter != aGlobalMap.end() )
        return *iter;
    return *(aGlobalMap.insert( sValue ).first);
}

static sal_Bool isFileUrl(const OString& fileName)
{
    if (fileName.indexOf("file://") == 0 )
        return sal_True;
    return sal_False;
}

OUString convertToFileUrl(const OString& fileName)
{
    if ( isFileUrl(fileName) )
    {
        return OStringToOUString(fileName, osl_getThreadTextEncoding());
    }

    OUString uUrlFileName;
    OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
    if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
    {
        OUString uWorkingDir;
        if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) {
            OSL_ASSERT(false);
        }
        if (FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName)
            != FileBase::E_None)
        {
            OSL_ASSERT(false);
        }
    } else
    {
        if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
            != FileBase::E_None)
        {
            OSL_ASSERT(false);
        }
    }

    return uUrlFileName;
}

//*************************************************************************
// FileStream
//*************************************************************************
FileStream::FileStream()
{
}

FileStream::FileStream(const OString& name, FileAccessMode mode)
    : m_pFile(NULL)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

FileStream::~FileStream()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
    }
}

sal_Bool FileStream::isValid()
{
    if ( m_pFile )
        return sal_True;

    return sal_False;
}

void FileStream::open(const OString& name, FileAccessMode mode)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

void FileStream::close()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
        m_pFile = NULL;
        m_name = OString();
    }
}

sal_Int32 FileStream::getSize()
{
    sal_Int32 pos = 0;
    sal_Int32 size = 0;
    if ( isValid() )
    {
        fflush(m_pFile);
        pos = ftell(m_pFile);
        if (!fseek(m_pFile, 0, SEEK_END))
            size = ftell(m_pFile);
        fseek(m_pFile, pos, SEEK_SET);
    }
    return size;
}

const sal_Char* FileStream::checkAccessMode(FileAccessMode mode)
{
    switch( mode )
    {
    case FAM_READ:
        return "r";
    case FAM_WRITE:
        return "w";
    case FAM_APPEND:
        return "a";
    case FAM_READWRITE_EXIST:
        return "r+";
    case FAM_READWRITE:
        return "w+";
    case FAM_READAPPEND:
        return "a+";
    }
    return "w+";
}

<commit_msg>INTEGRATION: CWS os2port01 (1.12.10); FILE MERGED 2006/12/28 15:02:27 ydario 1.12.10.1: OS/2 initial import.<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: global.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: vg $ $Date: 2007-09-20 15:03:42 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef _OSL_PROCESS_H_
#include <osl/process.h>
#endif
#ifndef _RTL_OSTRINGBUFFER_HXX_
#include <rtl/strbuf.hxx>
#endif
#ifndef _RTL_USTRING_HXX_
#include <rtl/ustring.hxx>
#endif

#ifndef     _OSL_THREAD_H_
#include    <osl/thread.h>
#endif
#ifndef     _OSL_FILE_HXX_
#include    <osl/file.hxx>
#endif

#include <stdlib.h>
#include <stdio.h>
#if defined(SAL_W32) || defined(SAL_OS2)
#include <io.h>
#include <direct.h>
#include <errno.h>
#endif

#ifdef UNX
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#endif

#ifndef _CODEMAKER_GLOBAL_HXX_
#include    <codemaker/global.hxx>
#endif

#ifdef SAL_UNX
#define SEPARATOR '/'
#else
#define SEPARATOR '\\'
#endif

using namespace ::rtl;
using namespace ::osl;

OString createFileNameFromType( const OString& destination,
                                const OString typeName,
                                const OString postfix,
                                sal_Bool bLowerCase,
                                const OString prefix )
{
    OString type(typeName);

    if (bLowerCase)
    {
        type = typeName.toAsciiLowerCase();
    }

    sal_uInt32 length = destination.getLength();

    sal_Bool withPoint = sal_False;
    if (length == 0)
    {
        length++;
        withPoint = sal_True;
    }

    length += prefix.getLength() + type.getLength() + postfix.getLength();

    sal_Bool withSeperator = sal_False;
    if (destination.getStr()[destination.getLength()] != '\\' &&
        destination.getStr()[destination.getLength()] != '/' &&
        type.getStr()[0] != '\\' &&
        type.getStr()[0] != '/')
    {
        length++;
        withSeperator = sal_True;
    }

    OStringBuffer nameBuffer(length);

    if (withPoint)
        nameBuffer.append('.');
    else
        nameBuffer.append(destination.getStr(), destination.getLength());

    if (withSeperator)
        nameBuffer.append("/", 1);

    OString tmpStr(type);
    if (prefix.getLength() > 0)
    {
        tmpStr = type.replaceAt(type.lastIndexOf('/')+1, 0, prefix);
    }

    nameBuffer.append(tmpStr.getStr(), tmpStr.getLength());
    nameBuffer.append(postfix.getStr(), postfix.getLength());

    OString fileName(nameBuffer);

    sal_Char token;
#ifdef SAL_UNX
    fileName = fileName.replace('\\', '/');
    token = '/';
#else
    fileName = fileName.replace('/', '\\');
    token = '\\';
#endif

    nameBuffer = OStringBuffer(length);

    sal_Int32 nIndex = 0;
    do
    {
        nameBuffer.append(fileName.getToken( 0, token, nIndex ).getStr());

        if (nameBuffer.getLength() == 0 || OString(".") == nameBuffer.getStr())
        {
            nameBuffer.append(token);
            continue;
        }

#if defined(SAL_UNX) || defined(SAL_OS2)
        if (mkdir((char*)nameBuffer.getStr(), 0777) == -1)
#else
           if (mkdir((char*)nameBuffer.getStr()) == -1)
#endif
        {
            if ( errno == ENOENT )
                return OString();
        }

        nameBuffer.append(token);
    }
    while ( nIndex >= 0 );

    return fileName;
}

sal_Bool fileExists(const OString& fileName)
{
    FILE  *f= fopen(fileName.getStr(), "r");

    if (f != NULL)
    {
        fclose(f);
        return sal_True;
    }

    return sal_False;
}

sal_Bool checkFileContent(const OString& targetFileName, const OString& tmpFileName)
{
    FILE  *target = fopen(targetFileName.getStr(), "r");
    FILE  *tmp = fopen(tmpFileName.getStr(), "r");
    sal_Bool ret = sal_False;

    if (target != NULL && tmp != NULL)
    {
        sal_Bool    bFindChanges = sal_False;
        sal_Char    buffer1[1024+1];
        sal_Char    buffer2[1024+1];
        sal_Int32   n1 = 0;
        sal_Int32   n2 = 0;

        while ( !bFindChanges && !feof(target) && !feof(tmp))
        {
            n1 = fread(buffer1, sizeof(sal_Char), 1024, target);
            n2 = fread(buffer2, sizeof(sal_Char), 1024, tmp);

            if ( n1 != n2 )
            {
                bFindChanges = sal_True;
            }
            else
            {
                if ( rtl_compareMemory(buffer1, buffer2, n2) != 0 )
                    bFindChanges =  sal_True;
            }
        }

        fclose(target);
        fclose(tmp);

        if ( bFindChanges )
        {
            if ( !unlink(targetFileName.getStr()) )
                if ( !rename(tmpFileName.getStr(), targetFileName.getStr()) )
                    ret = sal_True;
        }
        else
        {
            if ( !unlink(tmpFileName.getStr()) )
                ret = sal_True;
        }
    }

    return ret;
}

const OString inGlobalSet(const OUString & rValue)
{
    OString sValue( OUStringToOString(rValue, RTL_TEXTENCODING_UTF8) );
    static StringSet aGlobalMap;
    StringSet::iterator iter = aGlobalMap.find( sValue );
    if( iter != aGlobalMap.end() )
        return *iter;
    return *(aGlobalMap.insert( sValue ).first);
}

static sal_Bool isFileUrl(const OString& fileName)
{
    if (fileName.indexOf("file://") == 0 )
        return sal_True;
    return sal_False;
}

OUString convertToFileUrl(const OString& fileName)
{
    if ( isFileUrl(fileName) )
    {
        return OStringToOUString(fileName, osl_getThreadTextEncoding());
    }

    OUString uUrlFileName;
    OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
    if ( fileName.indexOf('.') == 0 || fileName.indexOf(SEPARATOR) < 0 )
    {
        OUString uWorkingDir;
        if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) {
            OSL_ASSERT(false);
        }
        if (FileBase::getAbsoluteFileURL(uWorkingDir, uFileName, uUrlFileName)
            != FileBase::E_None)
        {
            OSL_ASSERT(false);
        }
    } else
    {
        if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
            != FileBase::E_None)
        {
            OSL_ASSERT(false);
        }
    }

    return uUrlFileName;
}

//*************************************************************************
// FileStream
//*************************************************************************
FileStream::FileStream()
{
}

FileStream::FileStream(const OString& name, FileAccessMode mode)
    : m_pFile(NULL)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

FileStream::~FileStream()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
    }
}

sal_Bool FileStream::isValid()
{
    if ( m_pFile )
        return sal_True;

    return sal_False;
}

void FileStream::open(const OString& name, FileAccessMode mode)
{
    if ( name.getLength() > 0 )
    {
        m_name = name;
        m_pFile = fopen(m_name, checkAccessMode(mode));
    }
}

void FileStream::close()
{
    if ( isValid() )
    {
        fflush(m_pFile);
        fclose(m_pFile);
        m_pFile = NULL;
        m_name = OString();
    }
}

sal_Int32 FileStream::getSize()
{
    sal_Int32 pos = 0;
    sal_Int32 size = 0;
    if ( isValid() )
    {
        fflush(m_pFile);
        pos = ftell(m_pFile);
        if (!fseek(m_pFile, 0, SEEK_END))
            size = ftell(m_pFile);
        fseek(m_pFile, pos, SEEK_SET);
    }
    return size;
}

const sal_Char* FileStream::checkAccessMode(FileAccessMode mode)
{
    switch( mode )
    {
    case FAM_READ:
        return "r";
    case FAM_WRITE:
        return "w";
    case FAM_APPEND:
        return "a";
    case FAM_READWRITE_EXIST:
        return "r+";
    case FAM_READWRITE:
        return "w+";
    case FAM_READAPPEND:
        return "a+";
    }
    return "w+";
}

<|endoftext|>


<commit_before>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2018-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/webbrowser/processors/webbrowserprocessor.h>
#include <modules/webbrowser/interaction/cefinteractionhandler.h>
#include <modules/webbrowser/webbrowsermodule.h>
#include <modules/opengl/image/layergl.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/properties/minmaxproperty.h>
#include <inviwo/core/properties/propertyfactory.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/util/utilities.h>

#include <warn/push>
#include <warn/ignore/all>
#include <include/cef_app.h>
#include <warn/pop>

namespace inviwo {

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo WebBrowserProcessor::processorInfo_{
    "org.inviwo.webbrowser",  // Class identifier
    "Web browser",            // Display name
    "Web",                    // Category
    CodeState::Stable,        // Code state
    "GL, Web Browser",        // Tags
};
const ProcessorInfo WebBrowserProcessor::getProcessorInfo() const { return processorInfo_; }

WebBrowserProcessor::WebBrowserProcessor()
    : Processor()
    // Output from CEF is 8-bits per channel
    , background_("background")
    , outport_("webpage", DataVec4UInt8::get())
    , fileName_("fileName", "HTML file", "")
    , autoReloadFile_("autoReloadFile", "Auto Reload", true)
    , url_("URL", "URL", "http://www.inviwo.org")
    , reload_("reload", "Reload")
    , addPropertyGroup_("addProperty", "Add property to synchronize")
    , type_("property", "Property")
    , propertyHtmlId_("propertyHtmlId", "Html id")
    , add_("add", "Add")
    , runJS_("runJS", "Run JS")
    , js_("js", "JavaScript", "", InvalidationLevel::Valid)
    , sourceType_("sourceType", "Source",
                  {{"localFile", "Local File", SourceType::LocalFile},
                   {"webAddress", "Web Address", SourceType::WebAddress}})
    , picking_(this, 1, [&](PickingEvent* p) { cefInteractionHandler_.handlePickingEvent(p); })
    , cefToInviwoImageConverter_(picking_.getColor())
    , renderHandler_(new RenderHandlerGL([&]() {
        // Called as soon as new content is available
        // Queue an invalidation
        // Note: no need to queue invalidation using dispathFront since
        // RenderHandler calls will be made from the same thread.
        // dispatchFront([&] {
        invalidate(InvalidationLevel::InvalidOutput);
        //});
    }))
    , browserClient_(new WebBrowserClient(renderHandler_)) {
    addPort(background_);
    background_.setOptional(true);
    addPort(outport_);

    addProperty(sourceType_);
    addProperty(fileName_);
    addProperty(autoReloadFile_);
    addProperty(url_);
    url_.setVisible(false);
    addProperty(reload_);

    addProperty(runJS_);
    addProperty(js_);

    auto updateVisibility = [this]() {
        fileName_.setVisible(sourceType_ == SourceType::LocalFile);
        autoReloadFile_.setVisible(sourceType_ == SourceType::LocalFile);
        url_.setVisible(sourceType_ == SourceType::WebAddress);
    };
    updateVisibility();

    auto reload = [this]() { browser_->GetMainFrame()->LoadURL(getSource()); };

    sourceType_.onChange([this, reload, updateVisibility]() {
        updateVisibility();
        reload();
    });
    fileName_.onChange([this, reload]() {
        if (autoReloadFile_) {
            fileObserver_.setFilename(fileName_);
        }
        reload();
    });
    autoReloadFile_.onChange([this]() {
        if (autoReloadFile_) {
            fileObserver_.setFilename(fileName_);
        } else {
            fileObserver_.stop();
        }
    });
    url_.onChange(reload);
    reload_.onChange(reload);

    fileObserver_.onChange([this, reload]() {
        if (sourceType_ == SourceType::LocalFile) {
            reload();
        }
    });

    // Do not serialize options, they are generated in code
    type_.setSerializationMode(PropertySerializationMode::None);
    addPropertyGroup_.addProperty(type_);
    addPropertyGroup_.addProperty(propertyHtmlId_);
    addPropertyGroup_.addProperty(add_);
    addProperty(addPropertyGroup_);

    // Setup CEF browser
    CefWindowInfo window_info;

    CefBrowserSettings browserSettings;

    // Enable loading files from other locations than where the .html file is
    browserSettings.file_access_from_file_urls = STATE_ENABLED;

    browserSettings.windowless_frame_rate = 30;  // Must be between 1-60, 30 is default

    // in linux set a gtk widget, in windows a hwnd. If not available set nullptr - may cause
    // some render errors, in context-menu and plugins.
    window_info.SetAsWindowless(nullptr);  // nullptr means no transparency (site background colour)

    // Note that browserClient_ outlives this class so make sure to remove renderHandler_ in
    // destructor
    browser_ = CefBrowserHost::CreateBrowserSync(window_info, browserClient_, getSource(),
                                                 browserSettings, nullptr);
    // Observe when page has loaded
    browserClient_->addLoadHandler(this);
    // Do not process until frame is loaded
    isReady_.setUpdate([this]() { return allInportsAreReady() && !isBrowserLoading_; });
    // Inject events into CEF browser_
    cefInteractionHandler_.setHost(browser_->GetHost());
    cefInteractionHandler_.setRenderHandler(renderHandler_);
    addInteractionHandler(&cefInteractionHandler_);

    // Add all supported properties
    auto app = InviwoApplication::getPtr();
    for (auto propKey : app->getPropertyFactory()->getKeys()) {
        auto prop = app->getPropertyFactory()->create(propKey);
        if (browserClient_->propertyCefSynchronizer_->htmlWidgetFactory_.hasKey(prop.get())) {
            type_.addOption(prop->getClassIdentifier(),
                            filesystem::getFileExtension(prop->getClassIdentifier()), type_.size());
        }
    }
    type_.setCurrentStateAsDefault();
    propertyHtmlId_ = type_.getSelectedDisplayName();
    type_.onChange([&]() { propertyHtmlId_ = type_.getSelectedDisplayName(); });

    add_.onChange([&]() {
        auto key = type_.getSelectedIdentifier();
        auto p = getInviwoApplication()->getPropertyFactory()->create(key);

        auto id = propertyHtmlId_.get();
        try {
            util::validateIdentifier(id, "Property", IvwContext);
        } catch (Exception& ex) {
            LogError(ex.getMessage());
            return;
        }
        if (getPropertyByIdentifier(id) != nullptr) {
            LogError("Property with same id already added");
            return;
        }
        p->setIdentifier(id);
        p->setDisplayName(id);

        p->setSerializationMode(PropertySerializationMode::All);
        // InvalidationLevel::Valid is used to not get
        // invalidations from both CEF (html) and Qt
        p->setInvalidationLevel(InvalidationLevel::Valid);
        // Add property to processor before propertyCefSynchronizer to
        // include processor in property path
        addProperty(p.get(), true);

        browserClient_->propertyCefSynchronizer_->startSynchronize(p.get(), id);
        // Must reload page to connect property with Frame, see PropertyCefSynchronizer::OnLoadEnd
        browser_->GetMainFrame()->LoadURL(getSource());

        p.release();
    });
}

std::string WebBrowserProcessor::getSource() {
    std::string sourceString;
    if (sourceType_.get() == SourceType::LocalFile) {
        sourceString = "file://" + fileName_.get();
    } else if (sourceType_.get() == SourceType::WebAddress) {
        sourceString = url_.get();
    }
#ifndef NDEBUG
    // CEF does not allow empty urls in debug mode
    if (sourceString.empty()) {
        sourceString = "https://www.inviwo.org";
    }
#endif
    return sourceString;
}

WebBrowserProcessor::~WebBrowserProcessor() {
    browserClient_->removeLoadHandler(this);
    // Force close browser
    browser_->GetHost()->CloseBrowser(true);
    // Remove render handler since browserClient_ might not be destroyed until CefShutdown() is
    // called
    browserClient_->SetRenderHandler(NULL);
}

void WebBrowserProcessor::deserialize(Deserializer& d) {
    Processor::deserialize(d);

    for (auto prop : *this) {
        if (prop == &sourceType_ || prop == &fileName_ || prop == &url_ || prop == &reload_ ||
            prop == &addPropertyGroup_ || prop == &type_ || prop == &propertyHtmlId_ ||
            prop == &add_) {
            continue;
        }
        browserClient_->propertyCefSynchronizer_->startSynchronize(prop, prop->getIdentifier());
    }
    // Must reload page to connect property with Frame, see PropertyCefSynchronizer::OnLoadEnd
    browser_->GetMainFrame()->LoadURL(getSource());
}

void WebBrowserProcessor::OnLoadingStateChange(CefRefPtr<CefBrowser> browser, bool isLoading,
                                               bool /*canGoBack*/, bool /*canGoForward*/) {
    if (browser_ && browser->GetIdentifier() == browser_->GetIdentifier()) {
        isBrowserLoading_ = isLoading;
        isReady_.update();
    }
}

void WebBrowserProcessor::process() {
    if (js_.isModified()) {
        browser_->GetMainFrame()->ExecuteJavaScript(js_.get(), "", 1);
    }

    // Vertical flip of CEF output image
    cefToInviwoImageConverter_.convert(renderHandler_->getTexture2D(), outport_, &background_);
}

}  // namespace inviwo
<commit_msg>Webbrowser: Prevent empty script execution (error on Mac)<commit_after>/*********************************************************************************
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2018-2019 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/webbrowser/processors/webbrowserprocessor.h>
#include <modules/webbrowser/interaction/cefinteractionhandler.h>
#include <modules/webbrowser/webbrowsermodule.h>
#include <modules/opengl/image/layergl.h>
#include <inviwo/core/properties/ordinalproperty.h>
#include <inviwo/core/properties/minmaxproperty.h>
#include <inviwo/core/properties/propertyfactory.h>
#include <inviwo/core/util/filesystem.h>
#include <inviwo/core/util/utilities.h>

#include <warn/push>
#include <warn/ignore/all>
#include <include/cef_app.h>
#include <warn/pop>

namespace inviwo {

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo WebBrowserProcessor::processorInfo_{
    "org.inviwo.webbrowser",  // Class identifier
    "Web browser",            // Display name
    "Web",                    // Category
    CodeState::Stable,        // Code state
    "GL, Web Browser",        // Tags
};
const ProcessorInfo WebBrowserProcessor::getProcessorInfo() const { return processorInfo_; }

WebBrowserProcessor::WebBrowserProcessor()
    : Processor()
    // Output from CEF is 8-bits per channel
    , background_("background")
    , outport_("webpage", DataVec4UInt8::get())
    , fileName_("fileName", "HTML file", "")
    , autoReloadFile_("autoReloadFile", "Auto Reload", true)
    , url_("URL", "URL", "http://www.inviwo.org")
    , reload_("reload", "Reload")
    , addPropertyGroup_("addProperty", "Add property to synchronize")
    , type_("property", "Property")
    , propertyHtmlId_("propertyHtmlId", "Html id")
    , add_("add", "Add")
    , runJS_("runJS", "Run JS")
    , js_("js", "JavaScript", "", InvalidationLevel::Valid)
    , sourceType_("sourceType", "Source",
                  {{"localFile", "Local File", SourceType::LocalFile},
                   {"webAddress", "Web Address", SourceType::WebAddress}})
    , picking_(this, 1, [&](PickingEvent* p) { cefInteractionHandler_.handlePickingEvent(p); })
    , cefToInviwoImageConverter_(picking_.getColor())
    , renderHandler_(new RenderHandlerGL([&]() {
        // Called as soon as new content is available
        // Queue an invalidation
        // Note: no need to queue invalidation using dispathFront since
        // RenderHandler calls will be made from the same thread.
        // dispatchFront([&] {
        invalidate(InvalidationLevel::InvalidOutput);
        //});
    }))
    , browserClient_(new WebBrowserClient(renderHandler_)) {
    addPort(background_);
    background_.setOptional(true);
    addPort(outport_);

    addProperty(sourceType_);
    addProperty(fileName_);
    addProperty(autoReloadFile_);
    addProperty(url_);
    url_.setVisible(false);
    addProperty(reload_);

    addProperty(runJS_);
    addProperty(js_);

    auto updateVisibility = [this]() {
        fileName_.setVisible(sourceType_ == SourceType::LocalFile);
        autoReloadFile_.setVisible(sourceType_ == SourceType::LocalFile);
        url_.setVisible(sourceType_ == SourceType::WebAddress);
    };
    updateVisibility();

    auto reload = [this]() { browser_->GetMainFrame()->LoadURL(getSource()); };

    sourceType_.onChange([this, reload, updateVisibility]() {
        updateVisibility();
        reload();
    });
    fileName_.onChange([this, reload]() {
        if (autoReloadFile_) {
            fileObserver_.setFilename(fileName_);
        }
        reload();
    });
    autoReloadFile_.onChange([this]() {
        if (autoReloadFile_) {
            fileObserver_.setFilename(fileName_);
        } else {
            fileObserver_.stop();
        }
    });
    url_.onChange(reload);
    reload_.onChange(reload);

    fileObserver_.onChange([this, reload]() {
        if (sourceType_ == SourceType::LocalFile) {
            reload();
        }
    });

    // Do not serialize options, they are generated in code
    type_.setSerializationMode(PropertySerializationMode::None);
    addPropertyGroup_.addProperty(type_);
    addPropertyGroup_.addProperty(propertyHtmlId_);
    addPropertyGroup_.addProperty(add_);
    addProperty(addPropertyGroup_);

    // Setup CEF browser
    CefWindowInfo window_info;

    CefBrowserSettings browserSettings;

    // Enable loading files from other locations than where the .html file is
    browserSettings.file_access_from_file_urls = STATE_ENABLED;

    browserSettings.windowless_frame_rate = 30;  // Must be between 1-60, 30 is default

    // in linux set a gtk widget, in windows a hwnd. If not available set nullptr - may cause
    // some render errors, in context-menu and plugins.
    window_info.SetAsWindowless(nullptr);  // nullptr means no transparency (site background colour)

    // Note that browserClient_ outlives this class so make sure to remove renderHandler_ in
    // destructor
    browser_ = CefBrowserHost::CreateBrowserSync(window_info, browserClient_, getSource(),
                                                 browserSettings, nullptr);
    // Observe when page has loaded
    browserClient_->addLoadHandler(this);
    // Do not process until frame is loaded
    isReady_.setUpdate([this]() { return allInportsAreReady() && !isBrowserLoading_; });
    // Inject events into CEF browser_
    cefInteractionHandler_.setHost(browser_->GetHost());
    cefInteractionHandler_.setRenderHandler(renderHandler_);
    addInteractionHandler(&cefInteractionHandler_);

    // Add all supported properties
    auto app = InviwoApplication::getPtr();
    for (auto propKey : app->getPropertyFactory()->getKeys()) {
        auto prop = app->getPropertyFactory()->create(propKey);
        if (browserClient_->propertyCefSynchronizer_->htmlWidgetFactory_.hasKey(prop.get())) {
            type_.addOption(prop->getClassIdentifier(),
                            filesystem::getFileExtension(prop->getClassIdentifier()), type_.size());
        }
    }
    type_.setCurrentStateAsDefault();
    propertyHtmlId_ = type_.getSelectedDisplayName();
    type_.onChange([&]() { propertyHtmlId_ = type_.getSelectedDisplayName(); });

    add_.onChange([&]() {
        auto key = type_.getSelectedIdentifier();
        auto p = getInviwoApplication()->getPropertyFactory()->create(key);

        auto id = propertyHtmlId_.get();
        try {
            util::validateIdentifier(id, "Property", IvwContext);
        } catch (Exception& ex) {
            LogError(ex.getMessage());
            return;
        }
        if (getPropertyByIdentifier(id) != nullptr) {
            LogError("Property with same id already added");
            return;
        }
        p->setIdentifier(id);
        p->setDisplayName(id);

        p->setSerializationMode(PropertySerializationMode::All);
        // InvalidationLevel::Valid is used to not get
        // invalidations from both CEF (html) and Qt
        p->setInvalidationLevel(InvalidationLevel::Valid);
        // Add property to processor before propertyCefSynchronizer to
        // include processor in property path
        addProperty(p.get(), true);

        browserClient_->propertyCefSynchronizer_->startSynchronize(p.get(), id);
        // Must reload page to connect property with Frame, see PropertyCefSynchronizer::OnLoadEnd
        browser_->GetMainFrame()->LoadURL(getSource());

        p.release();
    });
}

std::string WebBrowserProcessor::getSource() {
    std::string sourceString;
    if (sourceType_.get() == SourceType::LocalFile) {
        sourceString = "file://" + fileName_.get();
    } else if (sourceType_.get() == SourceType::WebAddress) {
        sourceString = url_.get();
    }
#ifndef NDEBUG
    // CEF does not allow empty urls in debug mode
    if (sourceString.empty()) {
        sourceString = "https://www.inviwo.org";
    }
#endif
    return sourceString;
}

WebBrowserProcessor::~WebBrowserProcessor() {
    browserClient_->removeLoadHandler(this);
    // Force close browser
    browser_->GetHost()->CloseBrowser(true);
    // Remove render handler since browserClient_ might not be destroyed until CefShutdown() is
    // called
    browserClient_->SetRenderHandler(NULL);
}

void WebBrowserProcessor::deserialize(Deserializer& d) {
    Processor::deserialize(d);

    for (auto prop : *this) {
        if (prop == &sourceType_ || prop == &fileName_ || prop == &url_ || prop == &reload_ ||
            prop == &addPropertyGroup_ || prop == &type_ || prop == &propertyHtmlId_ ||
            prop == &add_) {
            continue;
        }
        browserClient_->propertyCefSynchronizer_->startSynchronize(prop, prop->getIdentifier());
    }
    // Must reload page to connect property with Frame, see PropertyCefSynchronizer::OnLoadEnd
    browser_->GetMainFrame()->LoadURL(getSource());
}

void WebBrowserProcessor::OnLoadingStateChange(CefRefPtr<CefBrowser> browser, bool isLoading,
                                               bool /*canGoBack*/, bool /*canGoForward*/) {
    if (browser_ && browser->GetIdentifier() == browser_->GetIdentifier()) {
        isBrowserLoading_ = isLoading;
        isReady_.update();
    }
}

void WebBrowserProcessor::process() {
    if (js_.isModified() && !js_.get().empty()) {
        browser_->GetMainFrame()->ExecuteJavaScript(js_.get(), "", 1);
    }

    // Vertical flip of CEF output image
    cefToInviwoImageConverter_.convert(renderHandler_->getTexture2D(), outport_, &background_);
}

}  // namespace inviwo
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright © 2019 Ruben Van Boxem
 *
 * 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 "ostream.h++"

#include <iostream>

namespace skui::css
{
  template<typename... ValueTypes>
  std::ostream& operator<<(std::ostream& os, const std::variant<ValueTypes...>& value)
  {
    std::visit([&os](auto&& v) { os << v; }, value);
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const inherit_t&)
  {
    return os << "inherit";
  }

  std::ostream& operator<<(std::ostream& os, const initial_t&)
  {
    return os << "initial";
  }

  std::ostream& operator<<(std::ostream& os, const color& color)
  {
    core::ostream_format_keeper keeper(os);

    return os << std::hex << std::uint32_t(color);
  }

  std::ostream& operator<<(std::ostream& os, const unit unit)
  {
    switch(unit)
    {
      case unit::mm:
        return os << "mm";
      case unit::cm:
        return os << "cm";
      case unit::in:
        return os << "in";
      case unit::px:
        return os << "px";
      case unit::pt:
        return os << "pt";
      case unit::pc:
        return os << "pc";
      case unit::em:
        return os << "em";
      case unit::ex:
        return os << "ex";
      case unit::ch:
        return os << "ch";
      case unit::rem:
        return os << "rem";
      case unit::vw:
        return os << "vw";
      case unit::vh:
        return os << "vh";
      case unit::vmin:
        return os << "vmin";
      case unit::vmax:
        return os << "vmax";
      case unit::percentage:
        return os << "%";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const length& length)
  {
    return os << length.value << ' ' << length.unit;
  }

  std::ostream& operator<<(std::ostream& os, const length_with_offset& length_with_offset)
  {
    os << length_with_offset.value;
    if(length_with_offset.offset != length{})
    {
      os << " (offset: " << length_with_offset.offset << ')';
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const position& position)
  {
    if(position == top)
      os << "top";
    else if(position == center)
      os << "center";
    else if(position == bottom)
      os << "bottom";
    else if(position == left)
      os << "left";
    else if(position == right)
      os << "right";
    else if(position == top_left)
      os << "top left";
    else if(position == top_right)
      os << "top right";
    else if(position == bottom_left)
      os << "bottom left";
    else if(position == bottom_right)
      os << "bottom right";
    else
      os << "position(" << position.x << ", " << position.y << ")";

    return os;
  }

  std::ostream& operator<<(std::ostream& os, const skui::css::time& time)
  {
    return os << time.count() << " ms";
  }

  std::ostream& operator<<(std::ostream& os, const steps& steps)
  {
    return os << "steps(" << steps.intervals << ", " << steps.change << ')';
  }

  std::ostream& operator<<(std::ostream& os, const cubic_bezier& cubic_bezier)
  {
    return os << "cubic-bezier(" << cubic_bezier.x1 << ", " << cubic_bezier.y1 << ", "
                                 << cubic_bezier.x2 << ", " << cubic_bezier.y2 << ')';
  }

  std::ostream& operator<<(std::ostream& os, const timing_function& timing_function)
  {
    std::visit([&os](const auto& value) { os << value; }, timing_function);
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const animation_direction& direction)
  {
    switch(direction)
    {
      case animation_direction::normal:
        return os << "normal";
      case animation_direction::reverse:
        return os << "reverse";
      case animation_direction::alternate:
        return os << "alternate";
      case animation_direction::alternate_reverse:
        return os << "alternate-reverse";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const fill_mode& mode)
  {
    switch(mode)
    {
      case fill_mode::none:
        return os << "none";
      case fill_mode::forwards:
        return os << "forwards";
      case fill_mode::backwards:
        return os << "backwards";
      case fill_mode::both:
        return os << "both";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const play_state& state)
  {
    switch(state)
    {
      case play_state::running:
        return os << "running";
      case play_state::paused:
        return os << "paused";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const infinite_t&)
  {
    return os << "infinite";
  }

  std::ostream& operator<<(std::ostream& os, const animation& animation)
  {
    return os << "animation\n{\n"
                 "  name: " << animation.name << ";\n"
                 "  duration: " << /*animation.duration <<*/ ";\n"
                 "  timing-function: " << animation.timing_function << ";\n"
                 "  delay: " << /*animation.delay <<*/ ";\n"
                 "  iteration_count: " << animation.iteration_count << ";\n"
                 "  direction: " << animation.direction << ";\n"
                 "  fill_mode: " << animation.fill_mode << ";\n"
                 "  play_state: " << animation.play_state << ";\n"
                                                             "}";
  }

  std::ostream& operator<<(std::ostream& os,
                           const std::vector<skui::css::color_stop>& colors)
  {
    for(auto it = colors.begin(); it != colors.end(); ++it)
    {
      os << *it;
      if(it+1 != colors.end())
        os << ", ";
    }
    return os;
  }

  std::ostream&operator<<(std::ostream& os, const color_stop& color_stop)
  {
    os << "color-stop(" << color_stop.color;
    if(color_stop.stop)
    {
      os << ", " << *color_stop.stop;
    }
    return os << ")";
  }

  std::ostream& operator<<(std::ostream& os,
                           const linear_gradient& linear_gradient)
  {
    if(linear_gradient.repeating)
      os << "repeating-";

    os << "linear-gradient(to ";
    std::visit([&os](auto&& direction) { os << direction; }, linear_gradient.direction);

    return os << ", " << linear_gradient.colors << ")";
  }
}
<commit_msg>Improve css::color ostream operator to always output same format.<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright © 2019 Ruben Van Boxem
 *
 * 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 "ostream.h++"

#include <iostream>

namespace skui::css
{
  template<typename... ValueTypes>
  std::ostream& operator<<(std::ostream& os, const std::variant<ValueTypes...>& value)
  {
    std::visit([&os](auto&& v) { os << v; }, value);
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const inherit_t&)
  {
    return os << "inherit";
  }

  std::ostream& operator<<(std::ostream& os, const initial_t&)
  {
    return os << "initial";
  }

  std::ostream& operator<<(std::ostream& os, const color& color)
  {
    core::ostream_format_keeper keeper(os);

    return os << std::setfill('0') << std::setw(8) << std::hex << std::uint32_t(color);
  }

  std::ostream& operator<<(std::ostream& os, const unit unit)
  {
    switch(unit)
    {
      case unit::mm:
        return os << "mm";
      case unit::cm:
        return os << "cm";
      case unit::in:
        return os << "in";
      case unit::px:
        return os << "px";
      case unit::pt:
        return os << "pt";
      case unit::pc:
        return os << "pc";
      case unit::em:
        return os << "em";
      case unit::ex:
        return os << "ex";
      case unit::ch:
        return os << "ch";
      case unit::rem:
        return os << "rem";
      case unit::vw:
        return os << "vw";
      case unit::vh:
        return os << "vh";
      case unit::vmin:
        return os << "vmin";
      case unit::vmax:
        return os << "vmax";
      case unit::percentage:
        return os << "%";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const length& length)
  {
    return os << length.value << ' ' << length.unit;
  }

  std::ostream& operator<<(std::ostream& os, const length_with_offset& length_with_offset)
  {
    os << length_with_offset.value;
    if(length_with_offset.offset != length{})
    {
      os << " (offset: " << length_with_offset.offset << ')';
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const position& position)
  {
    if(position == top)
      os << "top";
    else if(position == center)
      os << "center";
    else if(position == bottom)
      os << "bottom";
    else if(position == left)
      os << "left";
    else if(position == right)
      os << "right";
    else if(position == top_left)
      os << "top left";
    else if(position == top_right)
      os << "top right";
    else if(position == bottom_left)
      os << "bottom left";
    else if(position == bottom_right)
      os << "bottom right";
    else
      os << "position(" << position.x << ", " << position.y << ")";

    return os;
  }

  std::ostream& operator<<(std::ostream& os, const skui::css::time& time)
  {
    return os << time.count() << " ms";
  }

  std::ostream& operator<<(std::ostream& os, const steps& steps)
  {
    return os << "steps(" << steps.intervals << ", " << steps.change << ')';
  }

  std::ostream& operator<<(std::ostream& os, const cubic_bezier& cubic_bezier)
  {
    return os << "cubic-bezier(" << cubic_bezier.x1 << ", " << cubic_bezier.y1 << ", "
                                 << cubic_bezier.x2 << ", " << cubic_bezier.y2 << ')';
  }

  std::ostream& operator<<(std::ostream& os, const timing_function& timing_function)
  {
    std::visit([&os](const auto& value) { os << value; }, timing_function);
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const animation_direction& direction)
  {
    switch(direction)
    {
      case animation_direction::normal:
        return os << "normal";
      case animation_direction::reverse:
        return os << "reverse";
      case animation_direction::alternate:
        return os << "alternate";
      case animation_direction::alternate_reverse:
        return os << "alternate-reverse";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const fill_mode& mode)
  {
    switch(mode)
    {
      case fill_mode::none:
        return os << "none";
      case fill_mode::forwards:
        return os << "forwards";
      case fill_mode::backwards:
        return os << "backwards";
      case fill_mode::both:
        return os << "both";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const play_state& state)
  {
    switch(state)
    {
      case play_state::running:
        return os << "running";
      case play_state::paused:
        return os << "paused";
    }
    return os;
  }

  std::ostream& operator<<(std::ostream& os, const infinite_t&)
  {
    return os << "infinite";
  }

  std::ostream& operator<<(std::ostream& os, const animation& animation)
  {
    return os << "animation\n{\n"
                 "  name: " << animation.name << ";\n"
                 "  duration: " << /*animation.duration <<*/ ";\n"
                 "  timing-function: " << animation.timing_function << ";\n"
                 "  delay: " << /*animation.delay <<*/ ";\n"
                 "  iteration_count: " << animation.iteration_count << ";\n"
                 "  direction: " << animation.direction << ";\n"
                 "  fill_mode: " << animation.fill_mode << ";\n"
                 "  play_state: " << animation.play_state << ";\n"
                                                             "}";
  }

  std::ostream& operator<<(std::ostream& os,
                           const std::vector<skui::css::color_stop>& colors)
  {
    for(auto it = colors.begin(); it != colors.end(); ++it)
    {
      os << *it;
      if(it+1 != colors.end())
        os << ", ";
    }
    return os;
  }

  std::ostream&operator<<(std::ostream& os, const color_stop& color_stop)
  {
    os << "color-stop(" << color_stop.color;
    if(color_stop.stop)
    {
      os << ", " << *color_stop.stop;
    }
    return os << ")";
  }

  std::ostream& operator<<(std::ostream& os,
                           const linear_gradient& linear_gradient)
  {
    if(linear_gradient.repeating)
      os << "repeating-";

    os << "linear-gradient(to ";
    std::visit([&os](auto&& direction) { os << direction; }, linear_gradient.direction);

    return os << ", " << linear_gradient.colors << ")";
  }
}
<|endoftext|>


<commit_before>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/* Author: Dan Greenwald */

#include <moveit/warehouse/state_storage.h>
#include <boost/program_options/cmdline.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/variables_map.hpp>

#include <ros/ros.h>
#include <moveit_msgs/SaveRobotStateToWarehouse.h>
#include <moveit_msgs/ListRobotStatesInWarehouse.h>
#include <moveit_msgs/GetRobotStateFromWarehouse.h>
#include <moveit_msgs/CheckIfRobotStateExistsInWarehouse.h>
#include <moveit_msgs/DeleteRobotStateFromWarehouse.h>
#include <moveit_msgs/RenameRobotStateInWarehouse.h>

static const std::string ROBOT_DESCRIPTION="robot_description";

bool store_state(moveit_msgs::SaveRobotStateToWarehouse::Request&  request,
                 moveit_msgs::SaveRobotStateToWarehouse::Response& response,
                 moveit_warehouse::RobotStateStorage* rs)
{
  const moveit_msgs::RobotState& state = request.state;
  if ("" == request.name)
  {
    ROS_ERROR("You must specify a name to store a state");
    return response.success = false;
  }
  rs->addRobotState(request.state, request.name, request.robot);
  return response.success = true;
}

bool list_states(moveit_msgs::ListRobotStatesInWarehouse::Request&  request,
                  moveit_msgs::ListRobotStatesInWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  if ("" == request.regex)
  {
    rs->getKnownRobotStates(response.states, request.robot);
  }
  else
  {
    rs->getKnownRobotStates(request.regex, response.states, request.robot);
  }
  return true;
}

bool has_state(moveit_msgs::CheckIfRobotStateExistsInWarehouse::Request&  request,
               moveit_msgs::CheckIfRobotStateExistsInWarehouse::Response& response,
               moveit_warehouse::RobotStateStorage* rs)
{
  response.exists = rs->hasRobotState(request.name, request.robot);
  return true;
}

bool get_state(moveit_msgs::GetRobotStateFromWarehouse::Request&  request,
               moveit_msgs::GetRobotStateFromWarehouse::Response& response,
               moveit_warehouse::RobotStateStorage* rs)
{
  moveit_warehouse::RobotStateWithMetadata state_buffer;
  rs->getRobotState(state_buffer, request.name, request.robot);
  response.state = static_cast<const moveit_msgs::RobotState&>(*state_buffer);
  return true;
}

bool rename_state(moveit_msgs::RenameRobotStateInWarehouse::Request&  request,
                  moveit_msgs::RenameRobotStateInWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  rs->renameRobotState(request.old_name, request.new_name, request.robot);
  return true;
}

bool delete_state(moveit_msgs::DeleteRobotStateFromWarehouse::Request&  request,
                  moveit_msgs::DeleteRobotStateFromWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  rs->removeRobotState(request.name, request.robot);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "moveit_warehouse_services");

  ros::AsyncSpinner spinner(1);
  spinner.start();

  ros::NodeHandle node("~");
  std::string host; int port;
  node.param<std::string>("/warehouse_host", host, "");
  node.param<int>("/warehouse_port", port, 0);

  ROS_INFO("Connecting to warehouse on %s:%d", host.c_str(), port);
  moveit_warehouse::RobotStateStorage rs(host, port);

  std::vector<std::string> names;
  rs.getKnownRobotStates(names);
  if (names.empty())
    ROS_INFO("There are no previously stored robot states");
  else
  {
    ROS_INFO("Previously stored robot states:");
    for (std::size_t i = 0 ; i < names.size() ; ++i)
      ROS_INFO(" * %s", names[i].c_str());
  }

  boost::function<bool(moveit_msgs::SaveRobotStateToWarehouse::Request&  request,
                       moveit_msgs::SaveRobotStateToWarehouse::Response& response)>
    save_cb = boost::bind(&store_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::ListRobotStatesInWarehouse::Request&  request,
                       moveit_msgs::ListRobotStatesInWarehouse::Response& response)>
    list_cb = boost::bind(&list_states, _1, _2, &rs);

  boost::function<bool(moveit_msgs::GetRobotStateFromWarehouse::Request&  request,
                       moveit_msgs::GetRobotStateFromWarehouse::Response& response)>
    get_cb = boost::bind(&get_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::CheckIfRobotStateExistsInWarehouse::Request&  request,
                       moveit_msgs::CheckIfRobotStateExistsInWarehouse::Response& response)>
    has_cb = boost::bind(&has_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::RenameRobotStateInWarehouse::Request&  request,
                       moveit_msgs::RenameRobotStateInWarehouse::Response& response)>
    rename_cb = boost::bind(&rename_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::DeleteRobotStateFromWarehouse::Request&  request,
                       moveit_msgs::DeleteRobotStateFromWarehouse::Response& response)>
    delete_cb = boost::bind(&delete_state, _1, _2, &rs);

  ros::ServiceServer save_state_server   = node.advertiseService("save_robot_state",   save_cb);
  ros::ServiceServer list_states_server  = node.advertiseService("list_robot_states",  list_cb);
  ros::ServiceServer get_state_server    = node.advertiseService("get_robot_state",    get_cb);
  ros::ServiceServer has_state_server    = node.advertiseService("has_robot_state",    has_cb);
  ros::ServiceServer rename_state_server = node.advertiseService("rename_robot_state", rename_cb);
  ros::ServiceServer delete_state_server = node.advertiseService("delete_robot_state", delete_cb);

  ros::waitForShutdown();
  return 0;
}
<commit_msg>removed extraneous includes<commit_after>/*********************************************************************
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *********************************************************************/

/* Author: Dan Greenwald */

#include <ros/ros.h>
#include <moveit/warehouse/state_storage.h>
#include <moveit_msgs/SaveRobotStateToWarehouse.h>
#include <moveit_msgs/ListRobotStatesInWarehouse.h>
#include <moveit_msgs/GetRobotStateFromWarehouse.h>
#include <moveit_msgs/CheckIfRobotStateExistsInWarehouse.h>
#include <moveit_msgs/DeleteRobotStateFromWarehouse.h>
#include <moveit_msgs/RenameRobotStateInWarehouse.h>

static const std::string ROBOT_DESCRIPTION="robot_description";

bool store_state(moveit_msgs::SaveRobotStateToWarehouse::Request&  request,
                 moveit_msgs::SaveRobotStateToWarehouse::Response& response,
                 moveit_warehouse::RobotStateStorage* rs)
{
  const moveit_msgs::RobotState& state = request.state;
  if ("" == request.name)
  {
    ROS_ERROR("You must specify a name to store a state");
    return response.success = false;
  }
  rs->addRobotState(request.state, request.name, request.robot);
  return response.success = true;
}

bool list_states(moveit_msgs::ListRobotStatesInWarehouse::Request&  request,
                  moveit_msgs::ListRobotStatesInWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  if ("" == request.regex)
  {
    rs->getKnownRobotStates(response.states, request.robot);
  }
  else
  {
    rs->getKnownRobotStates(request.regex, response.states, request.robot);
  }
  return true;
}

bool has_state(moveit_msgs::CheckIfRobotStateExistsInWarehouse::Request&  request,
               moveit_msgs::CheckIfRobotStateExistsInWarehouse::Response& response,
               moveit_warehouse::RobotStateStorage* rs)
{
  response.exists = rs->hasRobotState(request.name, request.robot);
  return true;
}

bool get_state(moveit_msgs::GetRobotStateFromWarehouse::Request&  request,
               moveit_msgs::GetRobotStateFromWarehouse::Response& response,
               moveit_warehouse::RobotStateStorage* rs)
{
  moveit_warehouse::RobotStateWithMetadata state_buffer;
  rs->getRobotState(state_buffer, request.name, request.robot);
  response.state = static_cast<const moveit_msgs::RobotState&>(*state_buffer);
  return true;
}

bool rename_state(moveit_msgs::RenameRobotStateInWarehouse::Request&  request,
                  moveit_msgs::RenameRobotStateInWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  rs->renameRobotState(request.old_name, request.new_name, request.robot);
  return true;
}

bool delete_state(moveit_msgs::DeleteRobotStateFromWarehouse::Request&  request,
                  moveit_msgs::DeleteRobotStateFromWarehouse::Response& response,
                  moveit_warehouse::RobotStateStorage* rs)
{
  rs->removeRobotState(request.name, request.robot);
  return true;
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "moveit_warehouse_services");

  ros::AsyncSpinner spinner(1);
  spinner.start();

  ros::NodeHandle node("~");
  std::string host; int port;
  node.param<std::string>("/warehouse_host", host, "");
  node.param<int>("/warehouse_port", port, 0);

  ROS_INFO("Connecting to warehouse on %s:%d", host.c_str(), port);
  moveit_warehouse::RobotStateStorage rs(host, port);

  std::vector<std::string> names;
  rs.getKnownRobotStates(names);
  if (names.empty())
    ROS_INFO("There are no previously stored robot states");
  else
  {
    ROS_INFO("Previously stored robot states:");
    for (std::size_t i = 0 ; i < names.size() ; ++i)
      ROS_INFO(" * %s", names[i].c_str());
  }

  boost::function<bool(moveit_msgs::SaveRobotStateToWarehouse::Request&  request,
                       moveit_msgs::SaveRobotStateToWarehouse::Response& response)>
    save_cb = boost::bind(&store_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::ListRobotStatesInWarehouse::Request&  request,
                       moveit_msgs::ListRobotStatesInWarehouse::Response& response)>
    list_cb = boost::bind(&list_states, _1, _2, &rs);

  boost::function<bool(moveit_msgs::GetRobotStateFromWarehouse::Request&  request,
                       moveit_msgs::GetRobotStateFromWarehouse::Response& response)>
    get_cb = boost::bind(&get_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::CheckIfRobotStateExistsInWarehouse::Request&  request,
                       moveit_msgs::CheckIfRobotStateExistsInWarehouse::Response& response)>
    has_cb = boost::bind(&has_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::RenameRobotStateInWarehouse::Request&  request,
                       moveit_msgs::RenameRobotStateInWarehouse::Response& response)>
    rename_cb = boost::bind(&rename_state, _1, _2, &rs);

  boost::function<bool(moveit_msgs::DeleteRobotStateFromWarehouse::Request&  request,
                       moveit_msgs::DeleteRobotStateFromWarehouse::Response& response)>
    delete_cb = boost::bind(&delete_state, _1, _2, &rs);

  ros::ServiceServer save_state_server   = node.advertiseService("save_robot_state",   save_cb);
  ros::ServiceServer list_states_server  = node.advertiseService("list_robot_states",  list_cb);
  ros::ServiceServer get_state_server    = node.advertiseService("get_robot_state",    get_cb);
  ros::ServiceServer has_state_server    = node.advertiseService("has_robot_state",    has_cb);
  ros::ServiceServer rename_state_server = node.advertiseService("rename_robot_state", rename_cb);
  ros::ServiceServer delete_state_server = node.advertiseService("delete_robot_state", delete_cb);

  ros::waitForShutdown();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Extended error message for OAuth2 (#148)<commit_after><|endoftext|>


<commit_before>//===- tools/seec-trace-view/StreamStatePanel.cpp -------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Clang/MappedProcessState.hpp"
#include "seec/Clang/MappedStateMovement.hpp"
#include "seec/Clang/MappedStreamState.hpp"
#include "seec/Util/ScopeExit.hpp"
#include "seec/wxWidgets/StringConversion.hpp"

#include <wx/listbook.h>
#include <wx/stc/stc.h>

#include "ActionRecord.hpp"
#include "ActionReplay.hpp"
#include "CommonMenus.hpp"
#include "ProcessMoveEvent.hpp"
#include "StateAccessToken.hpp"
#include "StreamStatePanel.hpp"
#include "SourceViewerSettings.hpp"

//===----------------------------------------------------------------------===//
// StreamPanel
//===----------------------------------------------------------------------===//

/// \brief Shows the contents of a single FILE stream.
///
class StreamPanel final : public wxPanel
{
  /// Displays the data written to this FILE.
  wxStyledTextCtrl *Text;

  /// Parent's token for accessing the current state.
  std::shared_ptr<StateAccessToken> &ParentAccess;

  /// Pointer to the \c StreamState displayed by this \c StreamPanel.
  seec::cm::StreamState const *State;

  /// Character that the mouse is currently hovering over.
  long MouseOverPosition;

  /// Start of hover highlight range.
  long HighlightStart;

  /// Length of hover highlight range.
  long HighlightLength;

  /// Used to determine if a right-click was performed without moving.
  bool ClickUnmoved;

  /// \brief Clear highlighting used for mouse hover.
  ///
  void clearHighlight() {
    if (HighlightLength) {
      Text->IndicatorClearRange(HighlightStart, HighlightLength);
      HighlightStart = 0;
      HighlightLength = 0;
    }
  }

  /// \brief Updated the display using our current \c State.
  ///
  void update() {
    clearHighlight();
    MouseOverPosition = wxSTC_INVALID_POSITION;
    ClickUnmoved = false;

    Text->SetReadOnly(false);
    Text->SetValue(wxString{State->getWritten()});
    Text->SetReadOnly(true);
    Text->ScrollToEnd();
  }

  void OnTextMotion(wxMouseEvent &Ev) {
    // When we exit this scope, call Event.Skip() so that it is handled by the
    // default handler.
    auto const SkipEvent = seec::scopeExit([&](){ Ev.Skip(); });

    // Clear this in case we are inbetween right down and right up.
    ClickUnmoved = false;

    // Find the character that is being hovered over.
    long Position;
    auto const Test = Text->HitTest(Ev.GetPosition(), &Position);

    if (Test != wxTE_HT_ON_TEXT
        || Position < 0
        || Position >= State->getWritten().size()
        || Position == MouseOverPosition)
      return;

    clearHighlight();

    MouseOverPosition = Position;

    // Highlight the write that we are hovering over.
    auto const Write = State->getWriteAt(Position);
    HighlightStart = Write.Begin;
    HighlightLength = Write.End - Write.Begin;
    Text->IndicatorFillRange(HighlightStart, HighlightLength);
  }

  void OnTextLeave(wxMouseEvent &Ev) {
    MouseOverPosition = wxSTC_INVALID_POSITION;
    clearHighlight();
  }

  void OnRightDown(wxMouseEvent &Ev) {
    if (MouseOverPosition == wxSTC_INVALID_POSITION)
      return;
    ClickUnmoved = true;
    Ev.Skip();
  }

  void OnRightUp(wxMouseEvent &Ev) {
    if (!ClickUnmoved) {
      Ev.Skip();
      return;
    }

    wxMenu CM{};

    BindMenuItem(
      CM.Append(wxID_ANY,
                seec::getwxStringExOrEmpty("TraceViewer",
                  (char const *[]){"ContextualNavigation",
                                   "StreamRewindToWrite"})),
      [this] (wxEvent &) -> void {
        raiseMovementEvent(*this, ParentAccess,
          [=] (seec::cm::ProcessState &ProcessState) -> bool {
            return seec::cm::moveBackwardToStreamWriteAt(ProcessState,
                                                         *State,
                                                         MouseOverPosition);
          });
      });

    PopupMenu(&CM);
  }

public:
  /// \brief Construct a new \c StreamPanel for a given \c StreamState.
  ///
  StreamPanel(wxWindow *Parent,
              std::shared_ptr<StateAccessToken> &WithParentAccess,
              seec::cm::StreamState const &WithState)
  : wxPanel(Parent),
    Text(nullptr),
    ParentAccess(WithParentAccess),
    State(&WithState),
    MouseOverPosition(wxSTC_INVALID_POSITION),
    HighlightStart(0),
    HighlightLength(0),
    ClickUnmoved(false)
  {
    Text = new wxStyledTextCtrl(this, wxID_ANY);
    Text->SetReadOnly(true);

    // We only use one indicator (highlight), so set it here.
    setupAllSciIndicatorTypes(*Text);
    auto const Indicator = static_cast<int>(SciIndicatorType::CodeHighlight);
    Text->SetIndicatorCurrent(Indicator);

    Text->Bind(wxEVT_MOTION,       &StreamPanel::OnTextMotion, this);
    Text->Bind(wxEVT_LEAVE_WINDOW, &StreamPanel::OnTextLeave, this);
    Text->Bind(wxEVT_RIGHT_DOWN,   &StreamPanel::OnRightDown, this);
    Text->Bind(wxEVT_RIGHT_UP,     &StreamPanel::OnRightUp, this);

    auto const Sizer = new wxBoxSizer(wxHORIZONTAL);
    Sizer->Add(Text, wxSizerFlags().Proportion(1).Expand());
    SetSizerAndFit(Sizer);

    update();
  }

  /// \brief Update our \c StreamState.
  ///
  void update(seec::cm::StreamState const &WithState)
  {
    State = &WithState;
    update();
  }
};

//===----------------------------------------------------------------------===//
// StreamStatePanel
//===----------------------------------------------------------------------===//

StreamStatePanel::StreamStatePanel()
: Book(nullptr),
  Pages(),
  Notifier(nullptr),
  Recording(nullptr),
  CurrentAccess()
{}

StreamStatePanel::StreamStatePanel(wxWindow *Parent,
                                   ContextNotifier &WithNotifier,
                                   ActionRecord &WithRecording,
                                   ActionReplayFrame &WithReplay,
                                   wxWindowID ID,
                                   wxPoint const &Position,
                                   wxSize const &Size)
: StreamStatePanel()
{
  Create(Parent, WithNotifier, WithRecording, WithReplay, ID, Position, Size);
}

bool StreamStatePanel::Create(wxWindow *Parent,
                              ContextNotifier &WithNotifier,
                              ActionRecord &WithRecording,
                              ActionReplayFrame &WithReplay,
                              wxWindowID const ID,
                              wxPoint const &Position,
                              wxSize const &Size)
{
  if (!wxPanel::Create(Parent, ID, Position, Size))
    return false;

  Notifier = &WithNotifier;
  Recording = &WithRecording;

  Book = new wxListbook(this, ID, Position, Size);

  auto const Sizer = new wxBoxSizer(wxHORIZONTAL);
  Sizer->Add(Book, wxSizerFlags().Proportion(1).Expand());
  SetSizerAndFit(Sizer);

  return true;
}

void StreamStatePanel::show(std::shared_ptr<StateAccessToken> Access,
                            seec::cm::ProcessState const &Process,
                            seec::cm::ThreadState const &Thread)
{
  CurrentAccess = std::move(Access);

  // Remove pages that no longer exist, update those that do.
  for (auto It = Pages.begin(), End = Pages.end(); It != End; ++It) {
    if (auto const StreamPtr = Process.getStream(It->first)) {
      It->second->update(*StreamPtr);
    }
    else {
      Pages.erase(It);
    }
  }

  for (auto const &StreamEntry : Process.getStreams()) {
    auto const Address = StreamEntry.first;
    auto const It = Pages.lower_bound(Address);

    // If this FILE doesn't have a page then create one.
    if (It == Pages.end() || It->first != Address) {
      auto const StreamPage = new StreamPanel(this,
                                              CurrentAccess,
                                              StreamEntry.second);
      Book->AddPage(StreamPage, wxString{StreamEntry.second.getFilename()});
      Pages.insert(It, std::make_pair(Address, StreamPage));
    }
  }
}

void StreamStatePanel::clear()
{
  Book->DeleteAllPages();
  Pages.clear();
}
<commit_msg>Fix comparison between signed and unsigned values.<commit_after>//===- tools/seec-trace-view/StreamStatePanel.cpp -------------------------===//
//
//                                    SeeC
//
// This file is distributed under The MIT License (MIT). See LICENSE.TXT for
// details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
//===----------------------------------------------------------------------===//

#include "seec/Clang/MappedProcessState.hpp"
#include "seec/Clang/MappedStateMovement.hpp"
#include "seec/Clang/MappedStreamState.hpp"
#include "seec/Util/ScopeExit.hpp"
#include "seec/wxWidgets/StringConversion.hpp"

#include <wx/listbook.h>
#include <wx/stc/stc.h>

#include "ActionRecord.hpp"
#include "ActionReplay.hpp"
#include "CommonMenus.hpp"
#include "ProcessMoveEvent.hpp"
#include "StateAccessToken.hpp"
#include "StreamStatePanel.hpp"
#include "SourceViewerSettings.hpp"

//===----------------------------------------------------------------------===//
// StreamPanel
//===----------------------------------------------------------------------===//

/// \brief Shows the contents of a single FILE stream.
///
class StreamPanel final : public wxPanel
{
  /// Displays the data written to this FILE.
  wxStyledTextCtrl *Text;

  /// Parent's token for accessing the current state.
  std::shared_ptr<StateAccessToken> &ParentAccess;

  /// Pointer to the \c StreamState displayed by this \c StreamPanel.
  seec::cm::StreamState const *State;

  /// Character that the mouse is currently hovering over.
  long MouseOverPosition;

  /// Start of hover highlight range.
  long HighlightStart;

  /// Length of hover highlight range.
  long HighlightLength;

  /// Used to determine if a right-click was performed without moving.
  bool ClickUnmoved;

  /// \brief Clear highlighting used for mouse hover.
  ///
  void clearHighlight() {
    if (HighlightLength) {
      Text->IndicatorClearRange(HighlightStart, HighlightLength);
      HighlightStart = 0;
      HighlightLength = 0;
    }
  }

  /// \brief Updated the display using our current \c State.
  ///
  void update() {
    clearHighlight();
    MouseOverPosition = wxSTC_INVALID_POSITION;
    ClickUnmoved = false;

    Text->SetReadOnly(false);
    Text->SetValue(wxString{State->getWritten()});
    Text->SetReadOnly(true);
    Text->ScrollToEnd();
  }

  void OnTextMotion(wxMouseEvent &Ev) {
    // When we exit this scope, call Event.Skip() so that it is handled by the
    // default handler.
    auto const SkipEvent = seec::scopeExit([&](){ Ev.Skip(); });

    // Clear this in case we are inbetween right down and right up.
    ClickUnmoved = false;

    // Find the character that is being hovered over.
    long Position;
    auto const Test = Text->HitTest(Ev.GetPosition(), &Position);

    if (Test != wxTE_HT_ON_TEXT
        || Position < 0
        || static_cast<unsigned long>(Position) >= State->getWritten().size()
        || Position == MouseOverPosition)
      return;

    clearHighlight();

    MouseOverPosition = Position;

    // Highlight the write that we are hovering over.
    auto const Write = State->getWriteAt(Position);
    HighlightStart = Write.Begin;
    HighlightLength = Write.End - Write.Begin;
    Text->IndicatorFillRange(HighlightStart, HighlightLength);
  }

  void OnTextLeave(wxMouseEvent &Ev) {
    MouseOverPosition = wxSTC_INVALID_POSITION;
    clearHighlight();
  }

  void OnRightDown(wxMouseEvent &Ev) {
    if (MouseOverPosition == wxSTC_INVALID_POSITION)
      return;
    ClickUnmoved = true;
    Ev.Skip();
  }

  void OnRightUp(wxMouseEvent &Ev) {
    if (!ClickUnmoved) {
      Ev.Skip();
      return;
    }

    wxMenu CM{};

    BindMenuItem(
      CM.Append(wxID_ANY,
                seec::getwxStringExOrEmpty("TraceViewer",
                  (char const *[]){"ContextualNavigation",
                                   "StreamRewindToWrite"})),
      [this] (wxEvent &) -> void {
        raiseMovementEvent(*this, ParentAccess,
          [=] (seec::cm::ProcessState &ProcessState) -> bool {
            return seec::cm::moveBackwardToStreamWriteAt(ProcessState,
                                                         *State,
                                                         MouseOverPosition);
          });
      });

    PopupMenu(&CM);
  }

public:
  /// \brief Construct a new \c StreamPanel for a given \c StreamState.
  ///
  StreamPanel(wxWindow *Parent,
              std::shared_ptr<StateAccessToken> &WithParentAccess,
              seec::cm::StreamState const &WithState)
  : wxPanel(Parent),
    Text(nullptr),
    ParentAccess(WithParentAccess),
    State(&WithState),
    MouseOverPosition(wxSTC_INVALID_POSITION),
    HighlightStart(0),
    HighlightLength(0),
    ClickUnmoved(false)
  {
    Text = new wxStyledTextCtrl(this, wxID_ANY);
    Text->SetReadOnly(true);

    // We only use one indicator (highlight), so set it here.
    setupAllSciIndicatorTypes(*Text);
    auto const Indicator = static_cast<int>(SciIndicatorType::CodeHighlight);
    Text->SetIndicatorCurrent(Indicator);

    Text->Bind(wxEVT_MOTION,       &StreamPanel::OnTextMotion, this);
    Text->Bind(wxEVT_LEAVE_WINDOW, &StreamPanel::OnTextLeave, this);
    Text->Bind(wxEVT_RIGHT_DOWN,   &StreamPanel::OnRightDown, this);
    Text->Bind(wxEVT_RIGHT_UP,     &StreamPanel::OnRightUp, this);

    auto const Sizer = new wxBoxSizer(wxHORIZONTAL);
    Sizer->Add(Text, wxSizerFlags().Proportion(1).Expand());
    SetSizerAndFit(Sizer);

    update();
  }

  /// \brief Update our \c StreamState.
  ///
  void update(seec::cm::StreamState const &WithState)
  {
    State = &WithState;
    update();
  }
};

//===----------------------------------------------------------------------===//
// StreamStatePanel
//===----------------------------------------------------------------------===//

StreamStatePanel::StreamStatePanel()
: Book(nullptr),
  Pages(),
  Notifier(nullptr),
  Recording(nullptr),
  CurrentAccess()
{}

StreamStatePanel::StreamStatePanel(wxWindow *Parent,
                                   ContextNotifier &WithNotifier,
                                   ActionRecord &WithRecording,
                                   ActionReplayFrame &WithReplay,
                                   wxWindowID ID,
                                   wxPoint const &Position,
                                   wxSize const &Size)
: StreamStatePanel()
{
  Create(Parent, WithNotifier, WithRecording, WithReplay, ID, Position, Size);
}

bool StreamStatePanel::Create(wxWindow *Parent,
                              ContextNotifier &WithNotifier,
                              ActionRecord &WithRecording,
                              ActionReplayFrame &WithReplay,
                              wxWindowID const ID,
                              wxPoint const &Position,
                              wxSize const &Size)
{
  if (!wxPanel::Create(Parent, ID, Position, Size))
    return false;

  Notifier = &WithNotifier;
  Recording = &WithRecording;

  Book = new wxListbook(this, ID, Position, Size);

  auto const Sizer = new wxBoxSizer(wxHORIZONTAL);
  Sizer->Add(Book, wxSizerFlags().Proportion(1).Expand());
  SetSizerAndFit(Sizer);

  return true;
}

void StreamStatePanel::show(std::shared_ptr<StateAccessToken> Access,
                            seec::cm::ProcessState const &Process,
                            seec::cm::ThreadState const &Thread)
{
  CurrentAccess = std::move(Access);

  // Remove pages that no longer exist, update those that do.
  for (auto It = Pages.begin(), End = Pages.end(); It != End; ++It) {
    if (auto const StreamPtr = Process.getStream(It->first)) {
      It->second->update(*StreamPtr);
    }
    else {
      Pages.erase(It);
    }
  }

  for (auto const &StreamEntry : Process.getStreams()) {
    auto const Address = StreamEntry.first;
    auto const It = Pages.lower_bound(Address);

    // If this FILE doesn't have a page then create one.
    if (It == Pages.end() || It->first != Address) {
      auto const StreamPage = new StreamPanel(this,
                                              CurrentAccess,
                                              StreamEntry.second);
      Book->AddPage(StreamPage, wxString{StreamEntry.second.getFilename()});
      Pages.insert(It, std::make_pair(Address, StreamPage));
    }
  }
}

void StreamStatePanel::clear()
{
  Book->DeleteAllPages();
  Pages.clear();
}
<|endoftext|>


<commit_before>#pragma once
#include "declarations.hpp"
#include <gsl/gsl>
namespace mcpposutil
{
  /**
   * \brief Return start of data section.
   **/
  inline auto get_data_start() -> void *
  {
    return nullptr;
  }
  /**
   * \brief Return end of data section.
   **/
  inline auto get_data_end() -> void *
  {
    return nullptr;
  }
  /**
   * \brief Print current process map.
   **/
  inline void print_pmap(){};
}
<commit_msg>Fix OSX build<commit_after>#pragma once
#include "declarations.hpp"
#include <gsl/gsl>
namespace mcpposutil
{
  /**
   * \brief Return start of data section.
   **/
  inline auto get_data_start() -> void *
  {
    return nullptr;
  }
  /**
   * \brief Return end of data section.
   **/
  inline auto get_data_end() -> void *
  {
    return nullptr;
  }
  /**
   * \brief Print current process map.
   **/
  inline ::std::string pmap_as_string() { return {}; };
}
<|endoftext|>


<commit_before>// Copyright (c) 2012 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/sync/notifier/invalidation_notifier.h"

#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/mock_sync_notifier_observer.h"
#include "jingle/notifier/base/fake_base_task.h"
#include "jingle/notifier/base/notifier_options.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/url_request/url_request_test_util.h"
#include "sync/syncable/model_type.h"
#include "sync/syncable/model_type_payload_map.h"
#include "sync/util/weak_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sync_notifier {

namespace {

using ::testing::InSequence;
using ::testing::StrictMock;

class InvalidationNotifierTest : public testing::Test {
 protected:
  virtual void SetUp() {
    notifier::NotifierOptions notifier_options;
    // Note: URLRequestContextGetters are ref-counted.
    notifier_options.request_context_getter =
        new TestURLRequestContextGetter(message_loop_.message_loop_proxy());
    invalidation_notifier_.reset(
        new InvalidationNotifier(
            notifier_options,
            InvalidationVersionMap(),
            browser_sync::MakeWeakHandle(
                base::WeakPtr<InvalidationVersionTracker>()),
            "fake_client_info"));
    invalidation_notifier_->AddObserver(&mock_observer_);
  }

  virtual void TearDown() {
    invalidation_notifier_->RemoveObserver(&mock_observer_);
    // Stopping the invalidation notifier stops its scheduler, which deletes any
    // pending tasks without running them.  Some tasks "run and delete" another
    // task, so they must be run in order to avoid leaking the inner task.
    // Stopping does not schedule any tasks, so it's both necessary and
    // sufficient to drain the task queue before stopping the notifier.
    message_loop_.RunAllPending();
    invalidation_notifier_.reset();
  }

  MessageLoopForIO message_loop_;
  scoped_ptr<InvalidationNotifier> invalidation_notifier_;
  StrictMock<MockSyncNotifierObserver> mock_observer_;
  notifier::FakeBaseTask fake_base_task_;
};

TEST_F(InvalidationNotifierTest, Basic) {
  InSequence dummy;

  syncable::ModelTypePayloadMap type_payloads;
  type_payloads[syncable::PREFERENCES] = "payload";
  type_payloads[syncable::BOOKMARKS] = "";
  type_payloads[syncable::AUTOFILL] = "";

  EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
  EXPECT_CALL(mock_observer_, StoreState("new_fake_state"));
  EXPECT_CALL(mock_observer_,
              OnIncomingNotification(type_payloads,
                                     REMOTE_NOTIFICATION));
  EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));

  invalidation_notifier_->SetState("fake_state");
  invalidation_notifier_->SetUniqueId("fake_id");
  invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");

  invalidation_notifier_->OnConnect(fake_base_task_.AsWeakPtr());
  invalidation_notifier_->OnSessionStatusChanged(true);

  invalidation_notifier_->WriteState("new_fake_state");

  invalidation_notifier_->OnInvalidate(type_payloads);

  // Shouldn't trigger notification state change.
  invalidation_notifier_->OnDisconnect();
  invalidation_notifier_->OnConnect(fake_base_task_.AsWeakPtr());

  invalidation_notifier_->OnSessionStatusChanged(false);
}

}  // namespace

}  // namespace sync_notifier
<commit_msg>Revert 127587 - [Sync] Fix racy failure in invalidation_notifier_unittest.cc<commit_after>// Copyright (c) 2012 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/sync/notifier/invalidation_notifier.h"

#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/mock_sync_notifier_observer.h"
#include "jingle/notifier/base/fake_base_task.h"
#include "jingle/notifier/base/notifier_options.h"
#include "net/base/cert_verifier.h"
#include "net/base/host_resolver.h"
#include "net/url_request/url_request_test_util.h"
#include "sync/syncable/model_type.h"
#include "sync/syncable/model_type_payload_map.h"
#include "sync/util/weak_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace sync_notifier {

namespace {

using ::testing::InSequence;
using ::testing::StrictMock;

class InvalidationNotifierTest : public testing::Test {
 protected:
  virtual void SetUp() {
    notifier::NotifierOptions notifier_options;
    // Note: URLRequestContextGetters are ref-counted.
    notifier_options.request_context_getter =
        new TestURLRequestContextGetter(message_loop_.message_loop_proxy());
    invalidation_notifier_.reset(
        new InvalidationNotifier(
            notifier_options,
            InvalidationVersionMap(),
            browser_sync::MakeWeakHandle(
                base::WeakPtr<InvalidationVersionTracker>()),
            "fake_client_info"));
    invalidation_notifier_->AddObserver(&mock_observer_);
  }

  virtual void TearDown() {
    invalidation_notifier_->RemoveObserver(&mock_observer_);
    // Stopping the invalidation notifier stops its scheduler, which deletes any
    // pending tasks without running them.  Some tasks "run and delete" another
    // task, so they must be run in order to avoid leaking the inner task.
    // Stopping does not schedule any tasks, so it's both necessary and
    // sufficient to drain the task queue before stopping the notifier.
    message_loop_.RunAllPending();
    invalidation_notifier_.reset();
  }

  MessageLoop message_loop_;
  scoped_ptr<InvalidationNotifier> invalidation_notifier_;
  StrictMock<MockSyncNotifierObserver> mock_observer_;
  notifier::FakeBaseTask fake_base_task_;
};

TEST_F(InvalidationNotifierTest, Basic) {
  InSequence dummy;

  syncable::ModelTypePayloadMap type_payloads;
  type_payloads[syncable::PREFERENCES] = "payload";
  type_payloads[syncable::BOOKMARKS] = "";
  type_payloads[syncable::AUTOFILL] = "";

  EXPECT_CALL(mock_observer_, OnNotificationStateChange(true));
  EXPECT_CALL(mock_observer_, StoreState("new_fake_state"));
  EXPECT_CALL(mock_observer_,
              OnIncomingNotification(type_payloads,
                                     REMOTE_NOTIFICATION));
  EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));

  invalidation_notifier_->SetState("fake_state");
  invalidation_notifier_->SetUniqueId("fake_id");
  invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");

  invalidation_notifier_->OnConnect(fake_base_task_.AsWeakPtr());
  invalidation_notifier_->OnSessionStatusChanged(true);

  invalidation_notifier_->WriteState("new_fake_state");

  invalidation_notifier_->OnInvalidate(type_payloads);

  // Shouldn't trigger notification state change.
  invalidation_notifier_->OnDisconnect();
  invalidation_notifier_->OnConnect(fake_base_task_.AsWeakPtr());

  invalidation_notifier_->OnSessionStatusChanged(false);
}

}  // namespace

}  // namespace sync_notifier
<|endoftext|>