<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDataSetAlgorithm.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkDataSetAlgorithm.h"

#include "vtkCommand.h"
#include "vtkDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkRectilinearGrid.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredPoints.h"
#include "vtkUnstructuredGrid.h"

vtkCxxRevisionMacro(vtkDataSetAlgorithm, "1.12");
vtkStandardNewMacro(vtkDataSetAlgorithm);

//----------------------------------------------------------------------------
// Instantiate object so that cell data is not passed to output.
vtkDataSetAlgorithm::vtkDataSetAlgorithm()
{
  this->SetNumberOfInputPorts(1);
  this->SetNumberOfOutputPorts(1);
}

//----------------------------------------------------------------------------
vtkDataSet* vtkDataSetAlgorithm::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkDataSet* vtkDataSetAlgorithm::GetOutput(int port)
{
  return vtkDataSet::SafeDownCast(this->GetOutputDataObject(port));
}

//----------------------------------------------------------------------------
// Get the output as vtkImageData
vtkImageData *vtkDataSetAlgorithm::GetImageDataOutput()
{
  return vtkImageData::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkPolyData.
vtkPolyData *vtkDataSetAlgorithm::GetPolyDataOutput()
{
  return vtkPolyData::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkStructuredPoints.
vtkStructuredPoints *vtkDataSetAlgorithm::GetStructuredPointsOutput()
{
  return vtkStructuredPoints::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkStructuredGrid.
vtkStructuredGrid *vtkDataSetAlgorithm::GetStructuredGridOutput()
{
  return vtkStructuredGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkUnstructuredGrid.
vtkUnstructuredGrid *vtkDataSetAlgorithm::GetUnstructuredGridOutput()
{
  return vtkUnstructuredGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkRectilinearGrid.
vtkRectilinearGrid *vtkDataSetAlgorithm::GetRectilinearGridOutput()
{
  return vtkRectilinearGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(vtkDataObject* input)
{
  this->SetInput(0, input);
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(int index, vtkDataObject* input)
{
  if(input)
    {
    this->SetInputConnection(index, input->GetProducerPort());
    }
  else
    {
    // Setting a NULL input removes the connection.
    this->SetInputConnection(index, 0);
    }
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(vtkDataSet* input)
{
  this->SetInput(0, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(int index, vtkDataSet* input)
{
  this->SetInput(index, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(vtkDataObject* input)
{
  this->AddInput(0, input);
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(int index, vtkDataObject* input)
{
  if(input)
    {
    this->AddInputConnection(index, input->GetProducerPort());
    }
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(vtkDataSet* input)
{
  this->AddInput(0, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(int index, vtkDataSet* input)
{
  this->AddInput(index, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataSetAlgorithm::GetInput()
{
  return this->GetInput(0);
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataSetAlgorithm::GetInput(int port)
{
  if (this->GetNumberOfInputConnections(port) < 1)
    {
    return 0;
    }
  return this->GetExecutive()->GetInputData(port, 0);
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::ProcessRequest(
  vtkInformation* request,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  // generate the data
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
    {
    return this->RequestData(request, inputVector, outputVector);
    }

  // create the output
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
    {
    return this->RequestDataObject(request, inputVector, outputVector);
    }

  // execute information
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
    {
    return this->RequestInformation(request, inputVector, outputVector);
    }

  // set update extent
 if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
    {
    return this->RequestUpdateExtent(request, inputVector, outputVector);
    }
  return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::RequestDataObject(
  vtkInformation*,
  vtkInformationVector** inputVector ,
  vtkInformationVector* outputVector)
{
  vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
  if (!inInfo)
    {
    return 0;
    }
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));

  if (input)
    {
    // for each output
    for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
      {
      vtkInformation* info = outputVector->GetInformationObject(i);
      vtkDataSet *output = vtkDataSet::SafeDownCast(
        info->Get(vtkDataObject::DATA_OBJECT()));

      if (!output || !output->IsA(input->GetClassName()))
        {
        output = input->NewInstance();
        output->SetPipelineInformation(info);
        output->Delete();
        this->GetOutputPortInformation(0)->Set(
          vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType());
        }
      }
    return 1;
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::FillOutputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  // now add our info
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet");
  return 1;
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::FillInputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
  return 1;
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<commit_msg>STYLE: Fixed confusing code<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkDataSetAlgorithm.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkDataSetAlgorithm.h"

#include "vtkCommand.h"
#include "vtkDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPolyData.h"
#include "vtkRectilinearGrid.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStructuredGrid.h"
#include "vtkStructuredPoints.h"
#include "vtkUnstructuredGrid.h"

vtkCxxRevisionMacro(vtkDataSetAlgorithm, "1.13");
vtkStandardNewMacro(vtkDataSetAlgorithm);

//----------------------------------------------------------------------------
// Instantiate object so that cell data is not passed to output.
vtkDataSetAlgorithm::vtkDataSetAlgorithm()
{
  this->SetNumberOfInputPorts(1);
  this->SetNumberOfOutputPorts(1);
}

//----------------------------------------------------------------------------
vtkDataSet* vtkDataSetAlgorithm::GetOutput()
{
  return this->GetOutput(0);
}

//----------------------------------------------------------------------------
vtkDataSet* vtkDataSetAlgorithm::GetOutput(int port)
{
  return vtkDataSet::SafeDownCast(this->GetOutputDataObject(port));
}

//----------------------------------------------------------------------------
// Get the output as vtkImageData
vtkImageData *vtkDataSetAlgorithm::GetImageDataOutput()
{
  return vtkImageData::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkPolyData.
vtkPolyData *vtkDataSetAlgorithm::GetPolyDataOutput()
{
  return vtkPolyData::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkStructuredPoints.
vtkStructuredPoints *vtkDataSetAlgorithm::GetStructuredPointsOutput()
{
  return vtkStructuredPoints::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkStructuredGrid.
vtkStructuredGrid *vtkDataSetAlgorithm::GetStructuredGridOutput()
{
  return vtkStructuredGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkUnstructuredGrid.
vtkUnstructuredGrid *vtkDataSetAlgorithm::GetUnstructuredGridOutput()
{
  return vtkUnstructuredGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
// Get the output as vtkRectilinearGrid.
vtkRectilinearGrid *vtkDataSetAlgorithm::GetRectilinearGridOutput()
{
  return vtkRectilinearGrid::SafeDownCast(this->GetOutput());
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(vtkDataObject* input)
{
  this->SetInput(0, input);
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(int index, vtkDataObject* input)
{
  if(input)
    {
    this->SetInputConnection(index, input->GetProducerPort());
    }
  else
    {
    // Setting a NULL input removes the connection.
    this->SetInputConnection(index, 0);
    }
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(vtkDataSet* input)
{
  this->SetInput(0, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::SetInput(int index, vtkDataSet* input)
{
  this->SetInput(index, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(vtkDataObject* input)
{
  this->AddInput(0, input);
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(int index, vtkDataObject* input)
{
  if(input)
    {
    this->AddInputConnection(index, input->GetProducerPort());
    }
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(vtkDataSet* input)
{
  this->AddInput(0, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::AddInput(int index, vtkDataSet* input)
{
  this->AddInput(index, static_cast<vtkDataObject*>(input));
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataSetAlgorithm::GetInput()
{
  return this->GetInput(0);
}

//----------------------------------------------------------------------------
vtkDataObject* vtkDataSetAlgorithm::GetInput(int port)
{
  if (this->GetNumberOfInputConnections(port) < 1)
    {
    return 0;
    }
  return this->GetExecutive()->GetInputData(port, 0);
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::ProcessRequest(
  vtkInformation* request,
  vtkInformationVector** inputVector,
  vtkInformationVector* outputVector)
{
  // generate the data
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
    {
    return this->RequestData(request, inputVector, outputVector);
    }

  // create the output
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
    {
    return this->RequestDataObject(request, inputVector, outputVector);
    }

  // execute information
  if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
    {
    return this->RequestInformation(request, inputVector, outputVector);
    }

  // set update extent
 if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
    {
    return this->RequestUpdateExtent(request, inputVector, outputVector);
    }
  return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::RequestDataObject(
  vtkInformation*,
  vtkInformationVector** inputVector ,
  vtkInformationVector* outputVector)
{
  vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
  if (!inInfo)
    {
    return 0;
    }
  vtkDataSet *input = vtkDataSet::SafeDownCast(
    inInfo->Get(vtkDataObject::DATA_OBJECT()));

  if (input)
    {
    // for each output
    for(int i=0; i < this->GetNumberOfOutputPorts(); ++i)
      {
      vtkInformation* info = outputVector->GetInformationObject(i);
      vtkDataSet *output = vtkDataSet::SafeDownCast(
        info->Get(vtkDataObject::DATA_OBJECT()));

      if (!output || !output->IsA(input->GetClassName()))
        {
        vtkDataSet* newOutput = input->NewInstance();
        newOutput->SetPipelineInformation(info);
        newOutput->Delete();
        this->GetOutputPortInformation(0)->Set(
          vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType());
        }
      }
    return 1;
    }
  return 0;
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::FillOutputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  // now add our info
  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataSet");
  return 1;
}

//----------------------------------------------------------------------------
int vtkDataSetAlgorithm::FillInputPortInformation(
  int vtkNotUsed(port), vtkInformation* info)
{
  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
  return 1;
}

//----------------------------------------------------------------------------
void vtkDataSetAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}
<|endoftext|>


<commit_before>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        int i, fontHeight;
        int y = 0;

        fontHeight = getFont()->getHeight();

        /**
         * @todo Check cliprects so we do not have to iterate over elements in the list model
         */
        for (i = 0; i < mListModel->getNumberOfElements(); ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            generateAction();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            generateAction();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<commit_msg>List box has been optimized to only draw the items in the list that's actually visible.<commit_after>/*      _______   __   __   __   ______   __   __   _______   __   __
 *     / _____/\ / /\ / /\ / /\ / ____/\ / /\ / /\ / ___  /\ /  |\/ /\
 *    / /\____\// / // / // / // /\___\// /_// / // /\_/ / // , |/ / /
 *   / / /__   / / // / // / // / /    / ___  / // ___  / // /| ' / /
 *  / /_// /\ / /_// / // / // /_/_   / / // / // /\_/ / // / |  / /
 * /______/ //______/ //_/ //_____/\ /_/ //_/ //_/ //_/ //_/ /|_/ /
 * \______\/ \______\/ \_\/ \_____\/ \_\/ \_\/ \_\/ \_\/ \_\/ \_\/
 *
 * Copyright (c) 2004, 2005, 2006, 2007 Olof Naessn and Per Larsson
 *
 *                                                         Js_./
 * Per Larsson a.k.a finalman                          _RqZ{a<^_aa
 * Olof Naessn a.k.a jansem/yakslem                _asww7!uY`>  )\a//
 *                                                 _Qhm`] _f "'c  1!5m
 * Visit: http://guichan.darkbits.org             )Qk<P ` _: :+' .'  "{[
 *                                               .)j(] .d_/ '-(  P .   S
 * License: (BSD)                                <Td/Z <fP"5(\"??"\a.  .L
 * Redistribution and use in source and          _dV>ws?a-?'      ._/L  #'
 * binary forms, with or without                 )4d[#7r, .   '     )d`)[
 * modification, are permitted provided         _Q-5'5W..j/?'   -?!\)cam'
 * that the following conditions are met:       j<<WP+k/);.        _W=j f
 * 1. Redistributions of source code must       .$%w\/]Q  . ."'  .  mj$
 *    retain the above copyright notice,        ]E.pYY(Q]>.   a     J@\
 *    this list of conditions and the           j(]1u<sE"L,. .   ./^ ]{a
 *    following disclaimer.                     4'_uomm\.  )L);-4     (3=
 * 2. Redistributions in binary form must        )_]X{Z('a_"a7'<a"a,  ]"[
 *    reproduce the above copyright notice,       #}<]m7`Za??4,P-"'7. ).m
 *    this list of conditions and the            ]d2e)Q(<Q(  ?94   b-  LQ/
 *    following disclaimer in the                <B!</]C)d_, '(<' .f. =C+m
 *    documentation and/or other materials      .Z!=J ]e []('-4f _ ) -.)m]'
 *    provided with the distribution.          .w[5]' _[ /.)_-"+?   _/ <W"
 * 3. Neither the name of Guichan nor the      :$we` _! + _/ .        j?
 *    names of its contributors may be used     =3)= _f  (_yQmWW$#(    "
 *    to endorse or promote products derived     -   W,  sQQQQmZQ#Wwa]..
 *    from this software without specific        (js, \[QQW$QWW#?!V"".
 *    prior written permission.                    ]y:.<\..          .
 *                                                 -]n w/ '         [.
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT       )/ )/           !
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY         <  (; sac    ,    '
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING,               ]^ .-  %
 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF            c <   r
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR            aga<  <La
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE          5%  )P'-3L
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR        _bQf` y`..)a
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,          ,J?4P'.P"_(\?d'.,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES               _Pa,)!f/<[]/  ?"
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT      _2-..:. .r+_,.. .
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,     ?a.<%"'  " -'.a_ _,
 * 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.
 */

/*
 * For comments regarding functions please see the header file.
 */

#include "guichan/widgets/listbox.hpp"

#include "guichan/basiccontainer.hpp"
#include "guichan/font.hpp"
#include "guichan/graphics.hpp"
#include "guichan/key.hpp"
#include "guichan/listmodel.hpp"
#include "guichan/mouseinput.hpp"
#include "guichan/selectionlistener.hpp"

namespace gcn
{
    ListBox::ListBox()
        : mSelected(-1),
          mListModel(NULL),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    ListBox::ListBox(ListModel *listModel)
        : mSelected(-1),
          mWrappingEnabled(false)
    {
        setWidth(100);
        setListModel(listModel);
        setFocusable(true);

        addMouseListener(this);
        addKeyListener(this);
    }

    void ListBox::draw(Graphics* graphics)
    {
        graphics->setColor(getBackgroundColor());
        graphics->fillRectangle(Rectangle(0, 0, getWidth(), getHeight()));

        if (mListModel == NULL)
        {
            return;
        }

        graphics->setColor(getForegroundColor());
        graphics->setFont(getFont());

        const ClipRectangle currentClipArea = graphics->getCurrentClipArea();
        int fontHeight = getFont()->getHeight();
        int i = currentClipArea.y / getFont()->getHeight();
        int end = (currentClipArea.y + currentClipArea.height) / getFont()->getHeight();
        int y = 0;

        for (i = 0; i < end; ++i)
        {
            if (i == mSelected)
            {
                graphics->setColor(getSelectionColor());
                graphics->fillRectangle(Rectangle(0, y, getWidth(), fontHeight));
                graphics->setColor(getForegroundColor());
            }

            graphics->drawText(mListModel->getElementAt(i), 1, y);

            y += fontHeight;
        }
    }

    void ListBox::logic()
    {
        adjustSize();
    }

    int ListBox::getSelected() const
    {
        return mSelected;
    }

    void ListBox::setSelected(int selected)
    {
        if (mListModel == NULL)
        {
            mSelected = -1;
        }
        else
        {
            if (selected < 0)
            {
                mSelected = -1;
            }
            else if (selected >= mListModel->getNumberOfElements())
            {
                mSelected = mListModel->getNumberOfElements() - 1;
            }
            else
            {
                mSelected = selected;
            }

            Widget *par = getParent();
            if (par == NULL)
            {
                return;
            }

            Rectangle scroll;

            if (mSelected < 0)
            {
                scroll.y = 0;
            }
            else
            {
                scroll.y = getFont()->getHeight() * mSelected;
            }

            scroll.height = getFont()->getHeight();
            par->showWidgetPart(this, scroll);
        }

        distributeValueChangedEvent();
    }

    void ListBox::keyPressed(KeyEvent& keyEvent)
    {
        Key key = keyEvent.getKey();

        if (key.getValue() == Key::ENTER || key.getValue() == Key::SPACE)
        {
            generateAction();
            keyEvent.consume();
        }
        else if (key.getValue() == Key::UP)
        {
            setSelected(mSelected - 1);

            if (mSelected == -1)
            {
                if (mWrappingEnabled)
                {
                    setSelected(getListModel()->getNumberOfElements() - 1);
                }
                else
                {
                    setSelected(0);
                }
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::DOWN)
        {
            if (mWrappingEnabled
                && getSelected() == getListModel()->getNumberOfElements() - 1)
            {
                setSelected(0);
            }
            else
            {
                setSelected(getSelected() + 1);
            }

            keyEvent.consume();
        }
        else if (key.getValue() == Key::HOME)
        {
            setSelected(0);
            keyEvent.consume();
        }
        else if (key.getValue() == Key::END)
        {
            setSelected(getListModel()->getNumberOfElements() - 1);
            keyEvent.consume();
        }
    }

    void ListBox::mousePressed(MouseEvent& mouseEvent)
    {
        if (mouseEvent.getButton() == MouseEvent::LEFT)
        {
            setSelected(mouseEvent.getY() / getFont()->getHeight());
            generateAction();
        }
    }

    void ListBox::mouseWheelMovedUp(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            if (getSelected() > 0 )
            {
                setSelected(getSelected() - 1);
            }

            mouseEvent.consume();
        }
    }

    void ListBox::mouseWheelMovedDown(MouseEvent& mouseEvent)
    {
        if (isFocused())
        {
            setSelected(getSelected() + 1);

            mouseEvent.consume();
        }
    }

    void ListBox::mouseDragged(MouseEvent& mouseEvent)
    {
        mouseEvent.consume();
    }

    void ListBox::setListModel(ListModel *listModel)
    {
        mSelected = -1;
        mListModel = listModel;
        adjustSize();
    }

    ListModel* ListBox::getListModel()
    {
        return mListModel;
    }

    void ListBox::adjustSize()
    {
        if (mListModel != NULL)
        {
            setHeight(getFont()->getHeight() * mListModel->getNumberOfElements());
        }
    }

    bool ListBox::isWrappingEnabled() const
    {
        return mWrappingEnabled;
    }

    void ListBox::setWrappingEnabled(bool wrappingEnabled)
    {
        mWrappingEnabled = wrappingEnabled;
    }

    void ListBox::addSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.push_back(selectionListener);
    }

    void ListBox::removeSelectionListener(SelectionListener* selectionListener)
    {
        mSelectionListeners.remove(selectionListener);
    }

    void ListBox::distributeValueChangedEvent()
    {
        SelectionListenerIterator iter;

        for (iter = mSelectionListeners.begin(); iter != mSelectionListeners.end(); ++iter)
        {
            SelectionEvent event(this);
            (*iter)->valueChanged(event);
        }
    }
}
<|endoftext|>


<commit_before>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "windowedsurface.h"
#include "mimapphostedserverlogic.h"

#include <maliit/plugins/abstractwidgetssurface.h>

#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QWidget>

#if QT_VERSION >= 0x050000
#include <QGuiApplication>
#include <QPlatformNativeInterface>
#include <QVariant>
#include <QWindow>
#endif

#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/Xlib.h>
#endif

using Maliit::Plugins::AbstractSurface;

namespace Maliit {
namespace Server {

class WindowedSurface : public virtual Maliit::Plugins::AbstractSurface
{
public:
    WindowedSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent, QWidget *toplevel)
        : AbstractSurface(),
          mFactory(factory),
          mOptions(options),
          mParent(parent),
          mToplevel(toplevel),
          mActive(false),
          mVisible(false),
          mRelativePosition()
    {
        QWidget *parentWidget = 0;
        if (parent) {
            parentWidget = parent->mToplevel.data();
        }
        mToplevel->setParent(parentWidget, static_cast<Qt::WindowFlags>(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint));
        mToplevel->setAttribute(Qt::WA_X11DoNotAcceptFocus);
        mToplevel->setAutoFillBackground(false);
        mToplevel->setBackgroundRole(QPalette::NoRole);

        mToplevel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

        updateVisibility();
    }

    ~WindowedSurface()
    {
    }

    void show()
    {
        mVisible = true;
        updateVisibility();
    }

    void hide()
    {
        mVisible = false;
        updateVisibility();
    }

    QSize size() const
    {
        return mToplevel->size();
    }

    void setSize(const QSize &size)
    {
        const QSize& desktopSize = QApplication::desktop()->screenGeometry().size();

        if (mOptions & PositionCenterBottom) {
            mToplevel->setGeometry(QRect(QPoint((desktopSize.width() - size.width()) / 2, desktopSize.height() - size.height()), size));
        } else {
            mToplevel->resize(size);
        }
        mFactory->updateInputMethodArea();
    }

    QPoint relativePosition() const
    {
        return mRelativePosition;
    }

    void setRelativePosition(const QPoint &position)
    {
        mRelativePosition = position;
        QPoint parentPosition(0, 0);
        if (mParent) {
            parentPosition = mParent->mToplevel->pos();
        }
        mToplevel->move(parentPosition + mRelativePosition);
        mFactory->updateInputMethodArea();
    }

    QSharedPointer<AbstractSurface> parent() const
    {
        return mParent;
    }

    QPoint translateEventPosition(const QPoint &eventPosition, const QSharedPointer<AbstractSurface> &eventSurface = QSharedPointer<AbstractSurface>()) const
    {
        if (!eventSurface)
            return eventPosition;

        QSharedPointer<WindowedSurface> windowedSurface = qSharedPointerDynamicCast<WindowedSurface>(eventSurface);
        if (!windowedSurface)
            return QPoint();

        return -mToplevel->pos() + eventPosition + windowedSurface->mToplevel->pos();
    }

    void setActive(bool active)
    {
        mActive = active;
        updateVisibility();
    }

    void applicationFocusChanged(WId winId)
    {
        if (mParent)
            return;
#ifdef Q_WS_X11
        XSetTransientForHint(QX11Info::display(),
                             mToplevel->window()->effectiveWinId(),
                             winId);
#else
        Q_UNUSED(winId);
#endif
    }

    QRegion inputMethodArea()
    {
        if (!mToplevel->isVisible())
            return QRegion();

        return QRegion(mToplevel->geometry());
    }

private:
    void updateVisibility()
    {
        mToplevel->setVisible(mActive && mVisible);
        mFactory->updateInputMethodArea();
    }

protected:
    WindowedSurfaceFactory *mFactory;
    Options mOptions;
    QSharedPointer<WindowedSurface> mParent;
    QScopedPointer<QWidget> mToplevel;
    bool mActive;
    bool mVisible;
    QPoint mRelativePosition;
};

class GraphicsView : public QGraphicsView
{
public:
    GraphicsView()
        : QGraphicsView()
    {
        setWindowFlags(static_cast<Qt::WindowFlags>(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint));
        setAttribute(Qt::WA_X11DoNotAcceptFocus);
        setAutoFillBackground(false);
        setBackgroundRole(QPalette::NoRole);
        setBackgroundBrush(Qt::transparent);

        setAttribute(Qt::WA_TranslucentBackground);
        viewport()->setAutoFillBackground(false);
    }
};

class RootItem
    : public QGraphicsItem
{
private:
    QRectF m_rect;

public:
    explicit RootItem(QGraphicsItem *parent = 0)
        : QGraphicsItem(parent)
        , m_rect()
    {
        setFlag(QGraphicsItem::ItemHasNoContents);
    }

    void setRect(const QRectF &rect)
    {
        m_rect = rect;
    }

    virtual QRectF boundingRect() const
    {
        return m_rect;
    }

    virtual void paint(QPainter *,
                       const QStyleOptionGraphicsItem *,
                       QWidget *)
    {}
};

class WindowedGraphicsViewSurface : public WindowedSurface, public Maliit::Plugins::AbstractGraphicsViewSurface
{
public:
    WindowedGraphicsViewSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new GraphicsView),
          AbstractGraphicsViewSurface(),
          mRoot(0)
    {
        QGraphicsView *view = static_cast<QGraphicsView*>(mToplevel.data());
        view->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
        view->setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontSavePainterState);
        view->setFrameShape(QFrame::NoFrame);
        view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        QGraphicsScene *scene = new QGraphicsScene(view);
        view->setScene(scene);
    }

    ~WindowedGraphicsViewSurface() {}

    QGraphicsScene *scene() const
    {
        return view()->scene();
    }

    QGraphicsView *view() const
    {
        return static_cast<QGraphicsView*>(mToplevel.data());
    }

    void show()
    {
        WindowedSurface::show();

        const QRect rect(QPoint(), mToplevel->size());

        if (not mRoot) {
            scene()->addItem(mRoot = new RootItem);
            mRoot->setRect(rect);
            mRoot->show();
        }
    }

    void setSize(const QSize &size)
    {
        WindowedSurface::setSize(size);

        view()->setSceneRect(QRect(QPoint(), mToplevel->size()));
        if (mRoot) {
            mRoot->setRect(QRect(QPoint(), mToplevel->size()));
        }
    }

    void clear()
    {
        mRoot = 0;
        scene()->clear();
    }

    QGraphicsItem *root() const
    {
        return mRoot;
    }

private:
    RootItem *mRoot;
};

class WindowedWidgetSurface : public WindowedSurface, public Maliit::Plugins::AbstractWidgetSurface
{
public:
    WindowedWidgetSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new QWidget),
          AbstractWidgetSurface()
    {}

    QWidget* widget() const {
        return mToplevel.data();
    }
};

WindowedSurfaceFactory::WindowedSurfaceFactory()
    : AbstractSurfaceFactory()
    , surfaces()
    , mActive(false)
{
    connect(QApplication::desktop(), SIGNAL(resized(int)),
            this, SLOT(screenResized(int)));
}

WindowedSurfaceFactory::~WindowedSurfaceFactory()
{
}

QSize WindowedSurfaceFactory::screenSize() const
{
    return QApplication::desktop()->screenGeometry().size();
}

bool WindowedSurfaceFactory::supported(Maliit::Plugins::AbstractSurface::Options options) const
{
    return options & AbstractSurface::TypeGraphicsView;
}

QSharedPointer<AbstractSurface> WindowedSurfaceFactory::create(AbstractSurface::Options options, const QSharedPointer<AbstractSurface> &parent)
{
    QSharedPointer<WindowedSurface> defaultSurfaceParent(qSharedPointerDynamicCast<WindowedSurface>(parent));
    if (options & Maliit::Plugins::AbstractSurface::TypeGraphicsView) {
        QSharedPointer<WindowedGraphicsViewSurface> newSurface(new WindowedGraphicsViewSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->view(), options);
        return newSurface;
    } else if (options & Maliit::Plugins::AbstractSurface::TypeWidget) {
        QSharedPointer<WindowedWidgetSurface> newSurface(new WindowedWidgetSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->widget(), options);
        return newSurface;
    }
    return QSharedPointer<AbstractSurface>();
}

void WindowedSurfaceFactory::activate()
{
    mActive = true;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(true);
    }
}

void WindowedSurfaceFactory::deactivate()
{
    mActive = false;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(false);
    }
}

void WindowedSurfaceFactory::applicationFocusChanged(WId winId)
{
    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->applicationFocusChanged(winId);
        }
    }
}

void WindowedSurfaceFactory::screenResized(int)
{
    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->setSize(surface->size());
            if (surface->parent()) {
                surface->setRelativePosition(surface->relativePosition());
            }
        }
    }
    Q_EMIT screenSizeChanged(screenSize());
}

void WindowedSurfaceFactory::updateInputMethodArea()
{
    if (!mActive)
        return;

    QRegion inputMethodArea;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface && !surface->parent()) {
            inputMethodArea |= surface->inputMethodArea();
        }
    }

    Q_EMIT inputMethodAreaChanged(inputMethodArea);
}

} // namespace Server
} // namespace Maliit
<commit_msg>Fix infinite recursion when running embedded example under X11.<commit_after>/* * This file is part of meego-im-framework *
 *
 * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 * Contact: Nokia Corporation (directui@nokia.com)
 *
 * If you have questions regarding the use of this file, please contact
 * Nokia at directui@nokia.com.
 *
 * 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
 * and appearing in the file LICENSE.LGPL included in the packaging
 * of this file.
 */

#include "windowedsurface.h"
#include "mimdummyinputcontext.h"
#include "mimapphostedserverlogic.h"

#include <maliit/plugins/abstractwidgetssurface.h>

#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QWidget>

#if QT_VERSION >= 0x050000
#include <QGuiApplication>
#include <QPlatformNativeInterface>
#include <QVariant>
#include <QWindow>
#endif

#ifdef Q_WS_X11
#include <QX11Info>
#include <X11/Xlib.h>
#endif

using Maliit::Plugins::AbstractSurface;

namespace Maliit {
namespace Server {

class WindowedSurface : public virtual Maliit::Plugins::AbstractSurface
{
public:
    WindowedSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent, QWidget *toplevel)
        : AbstractSurface(),
          mFactory(factory),
          mOptions(options),
          mParent(parent),
          mToplevel(toplevel),
          mActive(false),
          mVisible(false),
          mRelativePosition()
    {
        QWidget *parentWidget = 0;
        if (parent) {
            parentWidget = parent->mToplevel.data();
        }
        mToplevel->setParent(parentWidget, static_cast<Qt::WindowFlags>(Qt::Dialog | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint));
        mToplevel->setAttribute(Qt::WA_X11DoNotAcceptFocus);
        mToplevel->setAutoFillBackground(false);
        mToplevel->setBackgroundRole(QPalette::NoRole);

        mToplevel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

        updateVisibility();
    }

    ~WindowedSurface()
    {
    }

    void show()
    {
        mVisible = true;
        updateVisibility();
    }

    void hide()
    {
        mVisible = false;
        updateVisibility();
    }

    QSize size() const
    {
        return mToplevel->size();
    }

    void setSize(const QSize &size)
    {
        const QSize& desktopSize = QApplication::desktop()->screenGeometry().size();

        if (mOptions & PositionCenterBottom) {
            mToplevel->setGeometry(QRect(QPoint((desktopSize.width() - size.width()) / 2, desktopSize.height() - size.height()), size));
        } else {
            mToplevel->resize(size);
        }
        mFactory->updateInputMethodArea();
    }

    QPoint relativePosition() const
    {
        return mRelativePosition;
    }

    void setRelativePosition(const QPoint &position)
    {
        mRelativePosition = position;
        QPoint parentPosition(0, 0);
        if (mParent) {
            parentPosition = mParent->mToplevel->pos();
        }
        mToplevel->move(parentPosition + mRelativePosition);
        mFactory->updateInputMethodArea();
    }

    QSharedPointer<AbstractSurface> parent() const
    {
        return mParent;
    }

    QPoint translateEventPosition(const QPoint &eventPosition, const QSharedPointer<AbstractSurface> &eventSurface = QSharedPointer<AbstractSurface>()) const
    {
        if (!eventSurface)
            return eventPosition;

        QSharedPointer<WindowedSurface> windowedSurface = qSharedPointerDynamicCast<WindowedSurface>(eventSurface);
        if (!windowedSurface)
            return QPoint();

        return -mToplevel->pos() + eventPosition + windowedSurface->mToplevel->pos();
    }

    void setActive(bool active)
    {
        mActive = active;
        updateVisibility();
    }

    void applicationFocusChanged(WId winId)
    {
        if (mParent)
            return;
#ifdef Q_WS_X11
        XSetTransientForHint(QX11Info::display(),
                             mToplevel->window()->effectiveWinId(),
                             winId);
#else
        Q_UNUSED(winId);
#endif
    }

    QRegion inputMethodArea()
    {
        if (!mToplevel->isVisible())
            return QRegion();

        return QRegion(mToplevel->geometry());
    }

private:
    void updateVisibility()
    {
        mToplevel->setVisible(mActive && mVisible);
        mFactory->updateInputMethodArea();
    }

protected:
    WindowedSurfaceFactory *mFactory;
    Options mOptions;
    QSharedPointer<WindowedSurface> mParent;
    QScopedPointer<QWidget> mToplevel;
    bool mActive;
    bool mVisible;
    QPoint mRelativePosition;
};

class GraphicsView : public QGraphicsView
{
public:
    GraphicsView()
        : QGraphicsView()
    {
        setWindowFlags(static_cast<Qt::WindowFlags>(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint));
        setAttribute(Qt::WA_X11DoNotAcceptFocus);
        setAutoFillBackground(false);
        setBackgroundRole(QPalette::NoRole);
        setBackgroundBrush(Qt::transparent);

        setAttribute(Qt::WA_TranslucentBackground);
        viewport()->setAutoFillBackground(false);
    }
};

class RootItem
    : public QGraphicsItem
{
private:
    QRectF m_rect;

public:
    explicit RootItem(QGraphicsItem *parent = 0)
        : QGraphicsItem(parent)
        , m_rect()
    {
        setFlag(QGraphicsItem::ItemHasNoContents);
    }

    void setRect(const QRectF &rect)
    {
        m_rect = rect;
    }

    virtual QRectF boundingRect() const
    {
        return m_rect;
    }

    virtual void paint(QPainter *,
                       const QStyleOptionGraphicsItem *,
                       QWidget *)
    {}
};

class WindowedGraphicsViewSurface : public WindowedSurface, public Maliit::Plugins::AbstractGraphicsViewSurface
{
public:
    WindowedGraphicsViewSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new GraphicsView),
          AbstractGraphicsViewSurface(),
          mRoot(0)
    {
        MIMDummyInputContext dummy;

        QGraphicsView *view = static_cast<QGraphicsView*>(mToplevel.data());
        view->setViewportUpdateMode(QGraphicsView::MinimalViewportUpdate);
        view->setOptimizationFlags(QGraphicsView::DontClipPainter | QGraphicsView::DontSavePainterState);
        view->setFrameShape(QFrame::NoFrame);
        view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        // Calling QGraphicsView::setScene() indirectly calls QWidget::inputContext() on the view.  If there isn't
        // an input context set on the widget, this calls QApplication::inputContext(), which leads to infinite
        // recursion if surface creation happens during input method creation and QT_IM_MODULE is set (for example
        // when embedding maliit-server in the application)
        view->setInputContext(&dummy);
        QGraphicsScene *scene = new QGraphicsScene(view);
        view->setScene(scene);
        view->setInputContext(0);
    }

    ~WindowedGraphicsViewSurface() {}

    QGraphicsScene *scene() const
    {
        return view()->scene();
    }

    QGraphicsView *view() const
    {
        return static_cast<QGraphicsView*>(mToplevel.data());
    }

    void show()
    {
        WindowedSurface::show();

        const QRect rect(QPoint(), mToplevel->size());

        if (not mRoot) {
            scene()->addItem(mRoot = new RootItem);
            mRoot->setRect(rect);
            mRoot->show();
        }
    }

    void setSize(const QSize &size)
    {
        WindowedSurface::setSize(size);

        view()->setSceneRect(QRect(QPoint(), mToplevel->size()));
        if (mRoot) {
            mRoot->setRect(QRect(QPoint(), mToplevel->size()));
        }
    }

    void clear()
    {
        mRoot = 0;
        scene()->clear();
    }

    QGraphicsItem *root() const
    {
        return mRoot;
    }

private:
    RootItem *mRoot;
};

class WindowedWidgetSurface : public WindowedSurface, public Maliit::Plugins::AbstractWidgetSurface
{
public:
    WindowedWidgetSurface(WindowedSurfaceFactory *factory, AbstractSurface::Options options, const QSharedPointer<WindowedSurface> &parent)
        : WindowedSurface(factory, options, parent, new QWidget),
          AbstractWidgetSurface()
    {}

    QWidget* widget() const {
        return mToplevel.data();
    }
};

WindowedSurfaceFactory::WindowedSurfaceFactory()
    : AbstractSurfaceFactory()
    , surfaces()
    , mActive(false)
{
    connect(QApplication::desktop(), SIGNAL(resized(int)),
            this, SLOT(screenResized(int)));
}

WindowedSurfaceFactory::~WindowedSurfaceFactory()
{
}

QSize WindowedSurfaceFactory::screenSize() const
{
    return QApplication::desktop()->screenGeometry().size();
}

bool WindowedSurfaceFactory::supported(Maliit::Plugins::AbstractSurface::Options options) const
{
    return options & AbstractSurface::TypeGraphicsView;
}

QSharedPointer<AbstractSurface> WindowedSurfaceFactory::create(AbstractSurface::Options options, const QSharedPointer<AbstractSurface> &parent)
{
    QSharedPointer<WindowedSurface> defaultSurfaceParent(qSharedPointerDynamicCast<WindowedSurface>(parent));
    if (options & Maliit::Plugins::AbstractSurface::TypeGraphicsView) {
        QSharedPointer<WindowedGraphicsViewSurface> newSurface(new WindowedGraphicsViewSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->view(), options);
        return newSurface;
    } else if (options & Maliit::Plugins::AbstractSurface::TypeWidget) {
        QSharedPointer<WindowedWidgetSurface> newSurface(new WindowedWidgetSurface(this, options, defaultSurfaceParent));
        surfaces.push_back(newSurface);
        Q_EMIT surfaceWidgetCreated(newSurface->widget(), options);
        return newSurface;
    }
    return QSharedPointer<AbstractSurface>();
}

void WindowedSurfaceFactory::activate()
{
    mActive = true;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(true);
    }
}

void WindowedSurfaceFactory::deactivate()
{
    mActive = false;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface)
            surface->setActive(false);
    }
}

void WindowedSurfaceFactory::applicationFocusChanged(WId winId)
{
    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->applicationFocusChanged(winId);
        }
    }
}

void WindowedSurfaceFactory::screenResized(int)
{
    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface) {
            surface->setSize(surface->size());
            if (surface->parent()) {
                surface->setRelativePosition(surface->relativePosition());
            }
        }
    }
    Q_EMIT screenSizeChanged(screenSize());
}

void WindowedSurfaceFactory::updateInputMethodArea()
{
    if (!mActive)
        return;

    QRegion inputMethodArea;

    Q_FOREACH(QWeakPointer<WindowedSurface> weakSurface, surfaces) {
        QSharedPointer<WindowedSurface> surface = weakSurface.toStrongRef();
        if (surface && !surface->parent()) {
            inputMethodArea |= surface->inputMethodArea();
        }
    }

    Q_EMIT inputMethodAreaChanged(inputMethodArea);
}

} // namespace Server
} // namespace Maliit
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: symbol.hxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: kz $ $Date: 2005-10-05 14:58:29 $
 *
 *  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 SYMBOL_HXX
#define SYMBOL_HXX

#ifndef _VOS_REFERNCE_HXX_
#include <vos/refernce.hxx>
#endif
#ifndef _FONT_HXX //autogen
#include <vcl/font.hxx>
#endif
#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif
#ifndef _DYNARY_HXX
#include <tools/dynary.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef UTILITY_HXX
#include "utility.hxx"
#endif
#ifndef _SMMOD_HXX
#include <smmod.hxx>
#endif

#define SS_ATTR_ACCESS      0x80

#define SYMBOLSET_NONE  0xFFFF
#define SYMBOL_NONE     0xFFFF

class SmSymSetManager;

////////////////////////////////////////////////////////////////////////////////

inline const String GetExportSymbolName( const String &rUiSymbolName )
{
    return SM_MOD1()->GetLocSymbolData().GetExportSymbolName( rUiSymbolName );
}

inline const String GetUiSymbolName( const String &rExportSymbolName )
{
    return SM_MOD1()->GetLocSymbolData().GetUiSymbolName( rExportSymbolName );
}

inline const String GetExportSymbolSetName( const String &rUiSymbolSetName )
{
    return SM_MOD1()->GetLocSymbolData().GetExportSymbolSetName( rUiSymbolSetName );
}

inline const String GetUiSymbolSetName( const String &rExportSymbolSetName )
{
    return SM_MOD1()->GetLocSymbolData().GetUiSymbolSetName( rExportSymbolSetName );
}

////////////////////////////////////////////////////////////////////////////////

class SmSym
{
    friend class SmSymSetManager;

    SmFace               Face;
    String               Name;
    String               aExportName;
    String               aSetName;
    SmSym               *pHashNext;
    SmSymSetManager     *pSymSetManager;
    sal_Unicode          Character;
    BYTE                 Attribut;
    BOOL                 bPredefined;
    BOOL                 bDocSymbol;

public:
    SmSym();
    SmSym(const SmSym& rSymbol);
    SmSym(const String& rName, const Font& rFont, sal_Unicode cChar,
          const String& rSet, BOOL bIsPredefined = FALSE);

    SmSym&      operator = (const SmSym& rSymbol);

    const Font&     GetFace() const { return Face; }
    sal_Unicode     GetCharacter() const { return Character; }
    const String&   GetName() const { return Name; }

    void            SetFace( const Font& rFont )        { Face = rFont; }
    void            SetCharacter( sal_Unicode cChar )   { Character = cChar; }
    void            SetName( const String &rTxt )       { Name = rTxt; }

    BOOL            IsPredefined() const    { return bPredefined; }
    const String &  GetSetName() const      { return aSetName; }
    void            SetSetName( const String &rName )    { aSetName = rName; }
    const String &  GetExportName() const   { return aExportName; }
    void            SetExportName( const String &rName )    { aExportName = rName; }

    BOOL            IsDocSymbol() const         { return bDocSymbol; }
    void            SetDocSymbol( BOOL bVal )   { bDocSymbol = bVal; }
};

DECLARE_LIST(SmListSym, SmSym *);
SV_DECL_PTRARR( SymbolArray, SmSym *, 32, 32 );

/**************************************************************************/

class SmSymSet
{
    friend class SmSymSetManager;

    SmListSym            SymbolList;
    String               Name;
    SmSymSetManager     *pSymSetManager;

public:
    SmSymSet();
    SmSymSet(const SmSymSet& rSymbolSet);
    SmSymSet(const String& rName);
    ~SmSymSet();

    SmSymSet&   operator = (const SmSymSet& rSymbolSet);

    const String&   GetName() const { return Name; }
    void            SetName(String& rName);
    USHORT          GetCount() const { return (USHORT) SymbolList.Count(); }

    const SmSym&    GetSymbol(USHORT SymbolNo) const
    {
        DBG_ASSERT(SymbolList.GetObject(SymbolNo), "Symbol nicht vorhanden");
        return *SymbolList.GetObject(SymbolNo);
    }

    USHORT      AddSymbol(SmSym* pSymbol);
    void        DeleteSymbol(USHORT SymbolNo);
    SmSym *     RemoveSymbol(USHORT SymbolNo);
    USHORT      GetSymbolPos(const String& rName);
};

DECLARE_DYNARRAY(SmArraySymSet, SmSymSet *)

/**************************************************************************/

class SmSymbolDialog;

struct SmSymSetManager_Impl
{
    SmArraySymSet       SymbolSets;
    SmSymSetManager &   rSymSetMgr;
    SmSym**             HashEntries;
    USHORT              NoSymbolSets;
    USHORT              NoHashEntries;
    BOOL                Modified;

    SmSymSetManager_Impl( SmSymSetManager &rMgr, USHORT HashTableSize );
    ~SmSymSetManager_Impl();

    SmSymSetManager_Impl & operator = ( const SmSymSetManager_Impl &rImpl );
};

class SmSymSetManager : public SfxListener
{
    friend struct SmSymSetManager_Impl;

    SmSymSetManager_Impl *pImpl;

    virtual void SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType,
                        const SfxHint& rHint, const TypeId& rHintType);

    UINT32      GetHashIndex(const String& rSymbolName);
    void        EnterHashTable(SmSym& rSymbol);
    void        EnterHashTable(SmSymSet& rSymbolSet);
    void        FillHashTable();
    void        Init();
    void        Exit();

public:
    SmSymSetManager(USHORT HashTableSize = 137);
    SmSymSetManager(const SmSymSetManager& rSymbolSetManager);
    ~SmSymSetManager();

    SmSymSetManager&   operator = (const SmSymSetManager& rSymbolSetManager);

    void        GetSymbols( std::vector< SmSym > &rSymbols ) const;

    USHORT      AddSymbolSet(SmSymSet* pSymbolSet);
    void        ChangeSymbolSet(SmSymSet* pSymbolSet);
    void        DeleteSymbolSet(USHORT SymbolSetNo);
    USHORT      GetSymbolSetPos(const String& rSymbolSetName) const;
    USHORT      GetSymbolSetCount() const { return pImpl->NoSymbolSets; }
    SmSymSet   *GetSymbolSet(USHORT SymbolSetNo) const
    {
        return pImpl->SymbolSets.Get(SymbolSetNo);
    }

    SmSym       *   GetSymbolByName(const String& rSymbolName);
    const SmSym *   GetSymbolByName(const String& rSymbolName) const
    {
        return ((SmSymSetManager *) this)->GetSymbolByName(rSymbolName);
    }

    void            AddReplaceSymbol( const SmSym & rSymbol );
    USHORT          GetSymbolCount() const;
    const SmSym *   GetSymbolByPos( USHORT nPos ) const;

    BOOL        IsModified() const { return pImpl->Modified; }
    void        SetModified(BOOL Modify) { pImpl->Modified = Modify; }

    void        Load();
    void        Save();
};

#endif

<commit_msg>INTEGRATION: CWS tl32 (1.14.138); FILE MERGED 2006/11/02 15:13:53 tl 1.14.138.1: #i69286# make starmath warning-free for unxsols4(.pro)<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: symbol.hxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: vg $ $Date: 2007-05-25 12:10:13 $
 *
 *  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 SYMBOL_HXX
#define SYMBOL_HXX

#ifndef _VOS_REFERNCE_HXX_
#include <vos/refernce.hxx>
#endif
#ifndef _FONT_HXX //autogen
#include <vcl/font.hxx>
#endif
#ifndef _LIST_HXX //autogen
#include <tools/list.hxx>
#endif
#ifndef _TOOLS_DEBUG_HXX //autogen
#include <tools/debug.hxx>
#endif
#ifndef _DYNARY_HXX
#include <tools/dynary.hxx>
#endif
#ifndef _SFXLSTNER_HXX //autogen
#include <svtools/lstner.hxx>
#endif
#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef UTILITY_HXX
#include "utility.hxx"
#endif
#ifndef _SMMOD_HXX
#include <smmod.hxx>
#endif

#define SS_ATTR_ACCESS      0x80

#define SYMBOLSET_NONE  0xFFFF
#define SYMBOL_NONE     0xFFFF

class SmSymSetManager;

////////////////////////////////////////////////////////////////////////////////

inline const String GetExportSymbolName( const String &rUiSymbolName )
{
    return SM_MOD1()->GetLocSymbolData().GetExportSymbolName( rUiSymbolName );
}

inline const String GetUiSymbolName( const String &rExportSymbolName )
{
    return SM_MOD1()->GetLocSymbolData().GetUiSymbolName( rExportSymbolName );
}

inline const String GetExportSymbolSetName( const String &rUiSymbolSetName )
{
    return SM_MOD1()->GetLocSymbolData().GetExportSymbolSetName( rUiSymbolSetName );
}

inline const String GetUiSymbolSetName( const String &rExportSymbolSetName )
{
    return SM_MOD1()->GetLocSymbolData().GetUiSymbolSetName( rExportSymbolSetName );
}

////////////////////////////////////////////////////////////////////////////////

class SmSym
{
    friend class SmSymSetManager;

    SmFace               Face;
    String               Name;
    String               aExportName;
    String               aSetName;
    SmSym               *pHashNext;
    SmSymSetManager     *pSymSetManager;
    sal_Unicode          Character;
    BYTE                 Attribut;
    BOOL                 bPredefined;
    BOOL                 bDocSymbol;

public:
    SmSym();
    SmSym(const SmSym& rSymbol);
    SmSym(const String& rName, const Font& rFont, sal_Unicode cChar,
          const String& rSet, BOOL bIsPredefined = FALSE);

    SmSym&      operator = (const SmSym& rSymbol);

    const Font&     GetFace() const { return Face; }
    sal_Unicode     GetCharacter() const { return Character; }
    const String&   GetName() const { return Name; }

    void            SetFace( const Font& rFont )        { Face = rFont; }
    void            SetCharacter( sal_Unicode cChar )   { Character = cChar; }
    void            SetName( const String &rTxt )       { Name = rTxt; }

    BOOL            IsPredefined() const    { return bPredefined; }
    const String &  GetSetName() const      { return aSetName; }
    void            SetSetName( const String &rName )    { aSetName = rName; }
    const String &  GetExportName() const   { return aExportName; }
    void            SetExportName( const String &rName )    { aExportName = rName; }

    BOOL            IsDocSymbol() const         { return bDocSymbol; }
    void            SetDocSymbol( BOOL bVal )   { bDocSymbol = bVal; }
};

DECLARE_LIST(SmListSym, SmSym *)
SV_DECL_PTRARR( SymbolArray, SmSym *, 32, 32 )

/**************************************************************************/

class SmSymSet
{
    friend class SmSymSetManager;

    SmListSym            SymbolList;
    String               Name;
    SmSymSetManager     *pSymSetManager;

public:
    SmSymSet();
    SmSymSet(const SmSymSet& rSymbolSet);
    SmSymSet(const String& rName);
    ~SmSymSet();

    SmSymSet&   operator = (const SmSymSet& rSymbolSet);

    const String&   GetName() const { return Name; }
    void            SetName(String& rName);
    USHORT          GetCount() const { return (USHORT) SymbolList.Count(); }

    const SmSym&    GetSymbol(USHORT SymbolNo) const
    {
        DBG_ASSERT(SymbolList.GetObject(SymbolNo), "Symbol nicht vorhanden");
        return *SymbolList.GetObject(SymbolNo);
    }

    USHORT      AddSymbol(SmSym* pSymbol);
    void        DeleteSymbol(USHORT SymbolNo);
    SmSym *     RemoveSymbol(USHORT SymbolNo);
    USHORT      GetSymbolPos(const String& rName);
};

DECLARE_DYNARRAY(SmArraySymSet, SmSymSet *)

/**************************************************************************/

class SmSymbolDialog;

struct SmSymSetManager_Impl
{
    SmArraySymSet       SymbolSets;
    SmSymSetManager &   rSymSetMgr;
    SmSym**             HashEntries;
    USHORT              NoSymbolSets;
    USHORT              NoHashEntries;
    BOOL                Modified;

    SmSymSetManager_Impl( SmSymSetManager &rMgr, USHORT HashTableSize );
    ~SmSymSetManager_Impl();

    SmSymSetManager_Impl & operator = ( const SmSymSetManager_Impl &rImpl );
};

class SmSymSetManager : public SfxListener
{
    friend struct SmSymSetManager_Impl;

    SmSymSetManager_Impl *pImpl;

    virtual void SFX_NOTIFY(SfxBroadcaster& rBC, const TypeId& rBCType,
                        const SfxHint& rHint, const TypeId& rHintType);

    UINT32      GetHashIndex(const String& rSymbolName);
    void        EnterHashTable(SmSym& rSymbol);
    void        EnterHashTable(SmSymSet& rSymbolSet);
    void        FillHashTable();
    void        Init();
    void        Exit();

public:
    SmSymSetManager(USHORT HashTableSize = 137);
    SmSymSetManager(const SmSymSetManager& rSymbolSetManager);
    ~SmSymSetManager();

    SmSymSetManager&   operator = (const SmSymSetManager& rSymbolSetManager);

    void        GetSymbols( std::vector< SmSym > &rSymbols ) const;

    USHORT      AddSymbolSet(SmSymSet* pSymbolSet);
    void        ChangeSymbolSet(SmSymSet* pSymbolSet);
    void        DeleteSymbolSet(USHORT SymbolSetNo);
    USHORT      GetSymbolSetPos(const String& rSymbolSetName) const;
    USHORT      GetSymbolSetCount() const { return pImpl->NoSymbolSets; }
    SmSymSet   *GetSymbolSet(USHORT SymbolSetNo) const
    {
        return pImpl->SymbolSets.Get(SymbolSetNo);
    }

    SmSym       *   GetSymbolByName(const String& rSymbolName);
    const SmSym *   GetSymbolByName(const String& rSymbolName) const
    {
        return ((SmSymSetManager *) this)->GetSymbolByName(rSymbolName);
    }

    void            AddReplaceSymbol( const SmSym & rSymbol );
    USHORT          GetSymbolCount() const;
    const SmSym *   GetSymbolByPos( USHORT nPos ) const;

    BOOL        IsModified() const { return pImpl->Modified; }
    void        SetModified(BOOL Modify) { pImpl->Modified = Modify; }

    void        Load();
    void        Save();
};

#endif

<|endoftext|>


<commit_before>/*
 Copyright (C) 2011 by Ivan Safrin

 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 "PolyScreenEntity.h"

inline double round(double x) { return floor(x + 0.5); }

using namespace Polycode;

ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
	color = new Color(1.0f,1.0f,1.0f,1.0f);
	width = 1;
	height = 1;
	hitwidth = 1;
	hitheight = 1;
	backfaceCulled = false;
	positionMode = POSITION_TOPLEFT;
	mouseOver = false;
	isDragged = false;

	dragOffsetX = 0;
	dragOffsetY = 0;
	parentEntity = NULL;
	zindex = 0;

	depthWrite = false;
	depthTest = false;

	focusable = false;
	hasFocus = false;
	focusChildren = false;
	focusedChild = NULL;
	blockMouseInput = false;

	snapToPixels = false;

	lastClickTicks = 0;
	dragLimits = NULL;

	xmouse = 0;
	ymouse = 0;

}

void ScreenEntity::focusNextChild() {
	int j = 0;
	if(focusedChild) {
		for(int i=0; i < children.size(); i++) {
			if(children[i] == focusedChild)
				j = i;
		}
	}

	for(int i=0; i < children.size(); i++) {
		if(((ScreenEntity*)children[j])->isFocusable() && children[j] != focusedChild) {
			focusChild(((ScreenEntity*)children[j]));
			return;
		}

		j++;
		if(j == children.size())
			j = 0;
	}
}

Number ScreenEntity::getRotation() {
	return this->getRoll();
}

void ScreenEntity::focusChild(ScreenEntity *child) {
	if(focusedChild != NULL) {
		focusedChild->onLoseFocus();
		focusedChild->hasFocus = false;
	}
	focusedChild = child;
	focusedChild->hasFocus = true;
	focusedChild->onGainFocus();
}

bool ScreenEntity::isFocusable() {
	return focusable;
}

void ScreenEntity::startDrag(Number xOffset, Number yOffset) {
	isDragged = true;
	dragOffsetX = xOffset;
	dragOffsetY = yOffset;
}

void ScreenEntity::stopDrag() {
	isDragged = false;
}

ScreenEntity::~ScreenEntity() {

}

void ScreenEntity::setBlendingMode(int newBlendingMode) {
	blendingMode = newBlendingMode;
}

void ScreenEntity::setPosition(Number x, Number y) {
	position.x  = x;
	position.y  = y;
	matrixDirty = true;
}

void ScreenEntity::setScale(Number x, Number y) {
	scale.x = x;
	scale.y = y;
	matrixDirty = true;
}

Number ScreenEntity::getWidth() {
	return width;
}

Number ScreenEntity::getHeight() {
	return height;
}

bool ScreenEntity::hitTest(Number x, Number y) {
	bool retVal = false;
//			Logger::log("hittest %f,%f in %f %f %f %f\n",x, y, position.x, position.y, hitwidth, hitheight);
	switch(positionMode) {
		case ScreenEntity::POSITION_TOPLEFT:

			if(x > position.x && x < (position.x + hitwidth)
				&& y > position.y && y < (position.y + hitheight))
				retVal = true;
		break;
		case ScreenEntity::POSITION_CENTER:
			if(x > (position.x - hitwidth/2.0f) && x < (position.x + hitwidth/2.0f)
				&& y > (position.y - hitheight/2.0f) && y < (position.y + hitheight/2.0f))
				retVal = true;
		break;
	}

	return retVal;
}

void ScreenEntity::setPositionMode(int newPositionMode) {
	positionMode = newPositionMode;
}

void ScreenEntity::_onKeyDown(PolyKEY key, wchar_t charCode) {
	onKeyDown(key, charCode);
	for(int i=0;i<children.size();i++) {
		((ScreenEntity*)children[i])->_onKeyDown(key, charCode);
	}
}

void ScreenEntity::_onKeyUp(PolyKEY key, wchar_t charCode) {
	onKeyUp(key, charCode);
	for(int i=0;i<children.size();i++) {
		((ScreenEntity*)children[i])->_onKeyUp(key, charCode);
	}
}

void ScreenEntity::setDragLimits(Polycode::Rectangle rect) {
	if(!dragLimits)
		dragLimits = new Polycode::Rectangle();
	dragLimits->x = rect.x;
	dragLimits->y = rect.y;
	dragLimits->w = rect.w;
	dragLimits->h = rect.h;
}

void ScreenEntity::clearDragLimits() {
	delete dragLimits;
	dragLimits = NULL;
}

void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {

	if(isDragged) {
		setPosition(x-dragOffsetX,y-dragOffsetY);
		if(dragLimits) {
			if(position.x < dragLimits->x)
				position.x = dragLimits->x;
			if(position.x > dragLimits->x + dragLimits->w)
				position.x = dragLimits->x + dragLimits->w;
			if(position.y < dragLimits->y)
				position.y = dragLimits->y;
			if(position.y > dragLimits->y + dragLimits->h)
				position.y = dragLimits->y + dragLimits->h;
		}
	}

	xmouse = x-position.x;
	ymouse = y-position.y;

	onMouseMove(x,y);
	if(enabled) {
		if(hitTest(x,y)) {
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEMOVE);
			if(!mouseOver) {
				dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOVER);
				mouseOver = true;
			}
		} else {
			if(mouseOver) {
				dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOUT);
				mouseOver = false;
			}
		}
	}

	if(enabled) {
		for(int i=0;i<children.size();i++) {
			((ScreenEntity*)children[i])->_onMouseMove(x-position.x,y-position.y, timestamp);
		}
	}
}

bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp) {
	bool retVal = false;
	if(hitTest(x,y) && enabled) {
		onMouseUp(x,y);

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;
		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
		retVal = true;
	} else {

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;

		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP_OUTSIDE);
	}

	if(enabled) {
		for(int i=0;i<children.size();i++) {
			((ScreenEntity*)children[i])->_onMouseUp(x-position.x,y-position.y, mouseButton, timestamp);
		}
	}
	return retVal;
}

void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
			doTest = false;
		}
	}

	if(doTest) {
		if(hitTest(x,y) && enabled) {
			onMouseWheelUp(x,y);
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_UP);
		}
		if(enabled) {
			for(int i=children.size()-1;i>=0;i--) {
				((ScreenEntity*)children[i])->_onMouseWheelUp(x-position.x,y-position.y, timestamp);
				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
						break;
				}
			}
		}
	}
}

void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
			doTest = false;
		}
	}

	if(doTest) {
		if(hitTest(x,y) && enabled) {
			onMouseWheelDown(x,y);
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_DOWN);
		}
		if(enabled) {
			for(int i=children.size()-1;i>=0;i--) {
				((ScreenEntity*)children[i])->_onMouseWheelDown(x-position.x,y-position.y, timestamp);
				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
						break;
				}
			}
		}
	}
}

bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp) {
	bool retVal = false;

	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
			doTest = false;
		}
	}

	if(doTest) {
	if(hitTest(x,y) && enabled) {
		onMouseDown(x,y);

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;
		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEDOWN);

		if(timestamp - lastClickTicks < 400) {
			InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
			inputEvent->mouseButton = mouseButton;
			dispatchEvent(inputEvent, InputEvent::EVENT_DOUBLECLICK);
		}
		lastClickTicks = timestamp;
		retVal = true;
	}
	if(enabled) {
		for(int i=children.size()-1;i>=0;i--) {

			((ScreenEntity*)children[i])->_onMouseDown(x-position.x,y-position.y, mouseButton, timestamp);
			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
				if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
				   break;
			}
		}
	}
	}

	return retVal;
}

void ScreenEntity::setRotation(Number rotation) {
	setRoll(rotation);
}

Vector2 ScreenEntity::getPosition2D() {
	return Vector2(position.x, position.y);
}

Matrix4 ScreenEntity::buildPositionMatrix() {
	Matrix4 posMatrix;
	switch(positionMode) {
		case POSITION_TOPLEFT:
//			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
			posMatrix.m[3][0] = (position.x+floor(width/2.0f)*scale.x)*matrixAdj;
			posMatrix.m[3][1] = (position.y+floor(height/2.0f)*scale.y)*matrixAdj;
			posMatrix.m[3][2] = position.z*matrixAdj;
		break;
		case POSITION_CENTER:
			posMatrix.m[3][0] = position.x*matrixAdj;
			posMatrix.m[3][1] = position.y*matrixAdj;
			posMatrix.m[3][2] = position.z*matrixAdj;
		break;
	}

	if(snapToPixels) {
		posMatrix.m[3][0] = round(posMatrix.m[3][0]);
		posMatrix.m[3][1] = round(posMatrix.m[3][1]);
		posMatrix.m[3][2] = round(posMatrix.m[3][2]);
	}

	return posMatrix;
}

void ScreenEntity::adjustMatrixForChildren() {
	if(positionMode == POSITION_TOPLEFT)
		renderer->translate2D(-floor(width/2.0f), -floor(height/2.0f));
}

/*
void ScreenEntity::transformAndRender() {

	Update();

	if(!renderer || !visible)
		return;

	renderer->pushMatrix();
	switch(positionMode) {
		case POSITION_TOPLEFT:
			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
		break;
		case POSITION_CENTER:
			renderer->translate2D(position.x, position.y);
		break;
	}
	renderer->scale2D(scale);
	renderer->rotate2D(rotation);
	if(parentEntity) {
		Color combined = getCombinedColor();
		renderer->setVertexColor(combined.r,combined.g,combined.b,combined.a);
	} else {
		renderer->setVertexColor(color.r,color.g,color.b,color.a);
	}

	renderer->setBlendingMode(blendingMode);
	Render();
	if(positionMode == POSITION_TOPLEFT)
		renderer->translate2D(-ceil(width/2.0f)*scale->x, -ceil(height/2.0f)*scale->y);
	renderChildren();
	renderer->popMatrix();
}
*/<commit_msg>Scale position and hit size before performing hit test.<commit_after>/*
 Copyright (C) 2011 by Ivan Safrin

 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 "PolyScreenEntity.h"

inline double round(double x) { return floor(x + 0.5); }

using namespace Polycode;

ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
	color = new Color(1.0f,1.0f,1.0f,1.0f);
	width = 1;
	height = 1;
	hitwidth = 1;
	hitheight = 1;
	backfaceCulled = false;
	positionMode = POSITION_TOPLEFT;
	mouseOver = false;
	isDragged = false;

	dragOffsetX = 0;
	dragOffsetY = 0;
	parentEntity = NULL;
	zindex = 0;

	depthWrite = false;
	depthTest = false;

	focusable = false;
	hasFocus = false;
	focusChildren = false;
	focusedChild = NULL;
	blockMouseInput = false;

	snapToPixels = false;

	lastClickTicks = 0;
	dragLimits = NULL;

	xmouse = 0;
	ymouse = 0;

}

void ScreenEntity::focusNextChild() {
	int j = 0;
	if(focusedChild) {
		for(int i=0; i < children.size(); i++) {
			if(children[i] == focusedChild)
				j = i;
		}
	}

	for(int i=0; i < children.size(); i++) {
		if(((ScreenEntity*)children[j])->isFocusable() && children[j] != focusedChild) {
			focusChild(((ScreenEntity*)children[j]));
			return;
		}

		j++;
		if(j == children.size())
			j = 0;
	}
}

Number ScreenEntity::getRotation() {
	return this->getRoll();
}

void ScreenEntity::focusChild(ScreenEntity *child) {
	if(focusedChild != NULL) {
		focusedChild->onLoseFocus();
		focusedChild->hasFocus = false;
	}
	focusedChild = child;
	focusedChild->hasFocus = true;
	focusedChild->onGainFocus();
}

bool ScreenEntity::isFocusable() {
	return focusable;
}

void ScreenEntity::startDrag(Number xOffset, Number yOffset) {
	isDragged = true;
	dragOffsetX = xOffset;
	dragOffsetY = yOffset;
}

void ScreenEntity::stopDrag() {
	isDragged = false;
}

ScreenEntity::~ScreenEntity() {

}

void ScreenEntity::setBlendingMode(int newBlendingMode) {
	blendingMode = newBlendingMode;
}

void ScreenEntity::setPosition(Number x, Number y) {
	position.x  = x;
	position.y  = y;
	matrixDirty = true;
}

void ScreenEntity::setScale(Number x, Number y) {
	scale.x = x;
	scale.y = y;
	matrixDirty = true;
}

Number ScreenEntity::getWidth() {
	return width;
}

Number ScreenEntity::getHeight() {
	return height;
}

bool ScreenEntity::hitTest(Number x, Number y) {
	bool retVal = false;
    // apply compound scale to test hit against
    Vector3 compScale = getCompoundScale();
    Number hx = position.x * compScale.x;
    Number hy = position.y * compScale.y;
    Number hw = hitwidth * compScale.x;
    Number hh = hitheight * compScale.y;
    //        Logger::log("hittest %f,%f in %f %f %f %f\n",x, y, hx, hy, hw, hh);
	switch(positionMode) {
		case ScreenEntity::POSITION_TOPLEFT:

            if(x > hx && x < (hx + hw)
                && y > hy && y < (hy + hh))
				retVal = true;
		break;
		case ScreenEntity::POSITION_CENTER:
            if(x > (hx - hw/2.0f) && x < (hx + hw/2.0f)
                && y > (hy - hh/2.0f) && y < (hy + hh/2.0f))
				retVal = true;
		break;
	}

	return retVal;
}

void ScreenEntity::setPositionMode(int newPositionMode) {
	positionMode = newPositionMode;
}

void ScreenEntity::_onKeyDown(PolyKEY key, wchar_t charCode) {
	onKeyDown(key, charCode);
	for(int i=0;i<children.size();i++) {
		((ScreenEntity*)children[i])->_onKeyDown(key, charCode);
	}
}

void ScreenEntity::_onKeyUp(PolyKEY key, wchar_t charCode) {
	onKeyUp(key, charCode);
	for(int i=0;i<children.size();i++) {
		((ScreenEntity*)children[i])->_onKeyUp(key, charCode);
	}
}

void ScreenEntity::setDragLimits(Polycode::Rectangle rect) {
	if(!dragLimits)
		dragLimits = new Polycode::Rectangle();
	dragLimits->x = rect.x;
	dragLimits->y = rect.y;
	dragLimits->w = rect.w;
	dragLimits->h = rect.h;
}

void ScreenEntity::clearDragLimits() {
	delete dragLimits;
	dragLimits = NULL;
}

void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {

	if(isDragged) {
		setPosition(x-dragOffsetX,y-dragOffsetY);
		if(dragLimits) {
			if(position.x < dragLimits->x)
				position.x = dragLimits->x;
			if(position.x > dragLimits->x + dragLimits->w)
				position.x = dragLimits->x + dragLimits->w;
			if(position.y < dragLimits->y)
				position.y = dragLimits->y;
			if(position.y > dragLimits->y + dragLimits->h)
				position.y = dragLimits->y + dragLimits->h;
		}
	}

	xmouse = x-position.x;
	ymouse = y-position.y;

	onMouseMove(x,y);
	if(enabled) {
		if(hitTest(x,y)) {
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEMOVE);
			if(!mouseOver) {
				dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOVER);
				mouseOver = true;
			}
		} else {
			if(mouseOver) {
				dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOUT);
				mouseOver = false;
			}
		}
	}

	if(enabled) {
		for(int i=0;i<children.size();i++) {
			((ScreenEntity*)children[i])->_onMouseMove(x-position.x,y-position.y, timestamp);
		}
	}
}

bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp) {
	bool retVal = false;
	if(hitTest(x,y) && enabled) {
		onMouseUp(x,y);

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;
		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
		retVal = true;
	} else {

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;

		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP_OUTSIDE);
	}

	if(enabled) {
		for(int i=0;i<children.size();i++) {
			((ScreenEntity*)children[i])->_onMouseUp(x-position.x,y-position.y, mouseButton, timestamp);
		}
	}
	return retVal;
}

void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
			doTest = false;
		}
	}

	if(doTest) {
		if(hitTest(x,y) && enabled) {
			onMouseWheelUp(x,y);
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_UP);
		}
		if(enabled) {
			for(int i=children.size()-1;i>=0;i--) {
				((ScreenEntity*)children[i])->_onMouseWheelUp(x-position.x,y-position.y, timestamp);
				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
						break;
				}
			}
		}
	}
}

void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
			doTest = false;
		}
	}

	if(doTest) {
		if(hitTest(x,y) && enabled) {
			onMouseWheelDown(x,y);
			dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_DOWN);
		}
		if(enabled) {
			for(int i=children.size()-1;i>=0;i--) {
				((ScreenEntity*)children[i])->_onMouseWheelDown(x-position.x,y-position.y, timestamp);
				if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
					if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
						break;
				}
			}
		}
	}
}

bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp) {
	bool retVal = false;

	bool doTest = true;

	if(hasMask) {
		if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
			doTest = false;
		}
	}

	if(doTest) {
	if(hitTest(x,y) && enabled) {
		onMouseDown(x,y);

		InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
		inputEvent->mouseButton = mouseButton;
		dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEDOWN);

		if(timestamp - lastClickTicks < 400) {
			InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
			inputEvent->mouseButton = mouseButton;
			dispatchEvent(inputEvent, InputEvent::EVENT_DOUBLECLICK);
		}
		lastClickTicks = timestamp;
		retVal = true;
	}
	if(enabled) {
		for(int i=children.size()-1;i>=0;i--) {

			((ScreenEntity*)children[i])->_onMouseDown(x-position.x,y-position.y, mouseButton, timestamp);
			if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
				if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
				   break;
			}
		}
	}
	}

	return retVal;
}

void ScreenEntity::setRotation(Number rotation) {
	setRoll(rotation);
}

Vector2 ScreenEntity::getPosition2D() {
	return Vector2(position.x, position.y);
}

Matrix4 ScreenEntity::buildPositionMatrix() {
	Matrix4 posMatrix;
	switch(positionMode) {
		case POSITION_TOPLEFT:
//			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
			posMatrix.m[3][0] = (position.x+floor(width/2.0f)*scale.x)*matrixAdj;
			posMatrix.m[3][1] = (position.y+floor(height/2.0f)*scale.y)*matrixAdj;
			posMatrix.m[3][2] = position.z*matrixAdj;
		break;
		case POSITION_CENTER:
			posMatrix.m[3][0] = position.x*matrixAdj;
			posMatrix.m[3][1] = position.y*matrixAdj;
			posMatrix.m[3][2] = position.z*matrixAdj;
		break;
	}

	if(snapToPixels) {
		posMatrix.m[3][0] = round(posMatrix.m[3][0]);
		posMatrix.m[3][1] = round(posMatrix.m[3][1]);
		posMatrix.m[3][2] = round(posMatrix.m[3][2]);
	}

	return posMatrix;
}

void ScreenEntity::adjustMatrixForChildren() {
	if(positionMode == POSITION_TOPLEFT)
		renderer->translate2D(-floor(width/2.0f), -floor(height/2.0f));
}

/*
void ScreenEntity::transformAndRender() {

	Update();

	if(!renderer || !visible)
		return;

	renderer->pushMatrix();
	switch(positionMode) {
		case POSITION_TOPLEFT:
			renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
		break;
		case POSITION_CENTER:
			renderer->translate2D(position.x, position.y);
		break;
	}
	renderer->scale2D(scale);
	renderer->rotate2D(rotation);
	if(parentEntity) {
		Color combined = getCombinedColor();
		renderer->setVertexColor(combined.r,combined.g,combined.b,combined.a);
	} else {
		renderer->setVertexColor(color.r,color.g,color.b,color.a);
	}

	renderer->setBlendingMode(blendingMode);
	Render();
	if(positionMode == POSITION_TOPLEFT)
		renderer->translate2D(-ceil(width/2.0f)*scale->x, -ceil(height/2.0f)*scale->y);
	renderChildren();
	renderer->popMatrix();
}
*/
<|endoftext|>