<commit_before>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "page_taskmanager.h"
#include "ui_page_taskmanager.h" //auto-generated from the .ui file

#define refreshRate 3000

#define memStyle QString("QLabel{background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:%1p rgb(100,100,200), stop:%2pa rgb(200,100,100), stop:%2pb rgb(200,100,100), stop:%3pa rgb(100,200,100), stop:%3pb rgb(100,200,100), stop:%4pa rgb(230, 230, 230), stop:%4pb rgb(230, 230, 230), stop:%5p white);\nborder: 1px solid black;\nborder-radius: 3px;}")

taskmanager_page::taskmanager_page(QWidget *parent, sysadm_client *core) : PageWidget(parent, core), ui(new Ui::taskmanager_ui){
  ui->setupUi(this);
  connect(ui->push_kill, SIGNAL(clicked()), this, SLOT(slot_kill_proc()) );
}

taskmanager_page::~taskmanager_page(){

}

//Initialize the CORE <-->Page connections
void taskmanager_page::setupCore(){
  connect(CORE, SIGNAL(newReply(QString, QString, QString, QJsonValue)), this, SLOT(ParseReply(QString, QString, QString, QJsonValue)) );
}

//Page embedded, go ahead and startup any core requests
void taskmanager_page::startPage(){
  //Let the main window know the name of this page
  emit ChangePageTitle( tr("Task Manager") );

  //Now run any CORE communications
  slotRequestProcInfo();
  slotRequestMemInfo();
  slotRequestCPUInfo();
  slotRequestCPUTempInfo();

  qDebug() << "Start page!";
}

// === PRIVATE SLOTS ===
void taskmanager_page::ParseReply(QString id, QString namesp, QString name, QJsonValue args){
  if( !id.startsWith("page_task_man_")){ return; }
 // qDebug() << "reply" << id;

  // Read in the PID list
  if ( id == "page_task_man_taskquery")
  {
    if ( ! args.isObject() )
      return;
    parsePIDS(args.toObject());
  }
  else if(id=="page_task_man_mem_check"){
    if(name!="error" && namesp!="error"){
      if(args.isObject() && args.toObject().contains("memorystats")){
        QJsonObject memO = args.toObject().value("memorystats").toObject();
	//qDebug() << "Got memory info:" << args << memO;
	int active, cache, freeM, inactive, wired; //MB
	active = cache = freeM = inactive = wired = 0;
	if(memO.contains("active")){ active = memO.value("active").toString().toInt(); }
	if(memO.contains("cache")){ cache = memO.value("cache").toString().toInt(); }
	if(memO.contains("free")){ freeM = memO.value("free").toString().toInt(); }
	if(memO.contains("inactive")){ inactive = memO.value("inactive").toString().toInt(); }
	if(memO.contains("wired")){ wired = memO.value("wired").toString().toInt(); }
	ShowMemInfo(active, cache, freeM, inactive, wired);
      }
    }

  }else if(id=="page_task_man_cpu_check" && name!="error" && namesp!="error" ){
    //CPU usage
    qDebug() << "Got CPU Usage:" << args;

  }else if(id=="page_task_man_cputemp_check" && name!="error" && namesp!="error" ){
    //CPU Temperature
    qDebug() << "Got CPU Temps:" << args;
  }
}

void taskmanager_page::parsePIDS(QJsonObject jsobj)
{
  //ui->taskWidget->clear();

  //qDebug() << "KEYS" << jsobj.keys();
  QStringList keys = jsobj.keys();
  if (keys.contains("message") ) {
    qDebug() << "MESSAGE" << jsobj.value("message").toString();
    return;
  }

  // Look for procinfo
  QJsonObject procobj = jsobj.value("procinfo").toObject();
  QStringList pids = procobj.keys();
  int doEvents = 0;
  for ( int i=0; i < pids.size(); i++ )
  {
    doEvents++;
    if ( doEvents > 50 ) {
      doEvents=0;
      QApplication::processEvents();
    }
    QString PID = pids.at(i);
    QJsonObject pidinfo = procobj.value(PID).toObject();

    // Check if we have this PID already
    QList<QTreeWidgetItem *> foundItems = ui->taskWidget->findItems(PID, Qt::MatchExactly, 0);
    if ( ! foundItems.isEmpty() )
    {
      foundItems.at(0)->setText(1, pidinfo.value("username").toString());
      foundItems.at(0)->setText(2, pidinfo.value("thr").toString());
      foundItems.at(0)->setText(3, pidinfo.value("pri").toString());
      foundItems.at(0)->setText(4, pidinfo.value("nice").toString());
      foundItems.at(0)->setText(5, pidinfo.value("size").toString());
      foundItems.at(0)->setText(6, pidinfo.value("res").toString());
      foundItems.at(0)->setText(7, pidinfo.value("state").toString());
      foundItems.at(0)->setText(8, pidinfo.value("cpu").toString());
      foundItems.at(0)->setText(9, pidinfo.value("time").toString());
      foundItems.at(0)->setText(10, pidinfo.value("wcpu").toString());
      foundItems.at(0)->setText(11, pidinfo.value("command").toString());
    } else {
      // Create the new taskWidget item
      new QTreeWidgetItem(ui->taskWidget, QStringList() << PID
          << pidinfo.value("username").toString()
          << pidinfo.value("thr").toString()
          << pidinfo.value("pri").toString()
          << pidinfo.value("nice").toString()
          << pidinfo.value("size").toString()
          << pidinfo.value("res").toString()
          << pidinfo.value("state").toString()
          << pidinfo.value("cpu").toString()
          << pidinfo.value("time").toString()
          << pidinfo.value("wcpu").toString()
          << pidinfo.value("command").toString()
          );
    }
  }

  // Now loop through the UI and look for pids to remove
  for ( int i=0; i<ui->taskWidget->topLevelItemCount(); i++ ) {
    // Check if this item exists in the PID list
    if ( ! pids.contains(ui->taskWidget->topLevelItem(i)->text(0)) ) {
      // No? Remove it
      ui->taskWidget->takeTopLevelItem(i);
    }
  }

  // Resize the widget to the new contents
  ui->taskWidget->header()->resizeSections(QHeaderView::ResizeToContents);
  ui->taskWidget->sortItems(10, Qt::DescendingOrder);
}

void taskmanager_page::ShowMemInfo(int active, int cache, int freeM, int inactive, int wired){
  //assemble the stylesheet
  int total = active+cache+freeM+inactive+wired;
  QString style = memStyle;
  QString TT = tr("Memory Stats (MB)")+"\n";
    TT.append( QString(tr(" - Total: %1")).arg(QString::number(total))+"\n");
  // Wired memory
  double perc = qRound( 10000.0* (wired/( (double) total)) )/10000.0;
  double laststop = 0;
    TT.append( QString(tr(" - Wired: %1 (%2)")).arg(QString::number(wired), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%1p",QString::number(perc)); //placement
    style.replace("%2pa",QString::number(perc+0.00001)); //start of next section
    laststop = perc+0.00001;
  double totperc = perc;
  //Active memory
  perc = qRound( 10000.0* (active/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Active: %1 (%2)")).arg(QString::number(active), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%2pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%3pa",QString::number(totperc+0.00001)); //start of next section
    laststop = totperc+0.00001;
  //cache memory
  perc = qRound( 10000.0* (cache/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Cache: %1 (%2)")).arg(QString::number(cache), QString::number(perc*100.0)+"%")+"\n" );
    style.replace("%3pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%4pa",QString::number(totperc+0.0001) ); //start of next section
    laststop = totperc+0.0001;
  ui->label_mem_stats->setText( QString(tr("Total Memory: %1 MB,   Used: %2%")).arg(QString::number(total), QString::number(totperc*100.0)) );
  //inactive memory
  perc = qRound( 10000.0* (inactive/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Inactive: %1 (%2)")).arg(QString::number(inactive), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%4pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%5p",QString::number(totperc+0.00001)); //start of next section
  //free memory
    TT.append( QString(tr(" - Free: %1 (%2)")).arg(QString::number(freeM), QString::number((1-totperc)*100.0)+"%") );
  //Now set the widgets
  //qDebug() << "styleSheet:" << style;
  ui->label_mem_stats->setToolTip(TT);
  ui->label_mem_stats->setStyleSheet(style);
}

void taskmanager_page::slotRequestProcInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "procinfo");
  CORE->communicate("page_task_man_taskquery", "sysadm", "systemmanager", jsobj);
  QTimer::singleShot(refreshRate, this, SLOT(slotRequestProcInfo()) );
}

void taskmanager_page::slotRequestMemInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "memorystats");
  CORE->communicate("page_task_man_mem_check", "sysadm", "systemmanager", jsobj);
  QTimer::singleShot(refreshRate, this, SLOT(slotRequestMemInfo()) );
}

void taskmanager_page::slotRequestCPUInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "cpupercentage");
  CORE->communicate("page_task_man_cpu_check", "sysadm", "systemmanager", jsobj);
  QTimer::singleShot(refreshRate, this, SLOT(slotRequestCPUInfo()) );
}

void taskmanager_page::slotRequestCPUTempInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "cputemps");
  CORE->communicate("page_task_man_cputemp_check", "sysadm", "systemmanager", jsobj);
  QTimer::singleShot(refreshRate, this, SLOT(slotRequestCPUTempInfo()) );
}

void taskmanager_page::slot_kill_proc(){
  //get the currently-selected PID
  QTreeWidgetItem *tmp = ui->taskWidget->currentItem();
  if(tmp==0){ return; }
  QString pid = tmp->text(0); //column 0 is the PID
  //Now send the request
  QJsonObject jsobj;
  jsobj.insert("action", "killproc");
  jsobj.insert("pid",pid);
  jsobj.insert("signal","KILL");
  CORE->communicate("page_task_man_kill_proc", "sysadm", "systemmanager", jsobj);
}
<commit_msg>Only start the timers after the previous response has come back. This prevents multiple identical requests being kicked off<commit_after>//===========================================
//  PC-BSD source code
//  Copyright (c) 2016, PC-BSD Software/iXsystems
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "page_taskmanager.h"
#include "ui_page_taskmanager.h" //auto-generated from the .ui file

#define refreshRate 3000

#define memStyle QString("QLabel{background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:%1p rgb(100,100,200), stop:%2pa rgb(200,100,100), stop:%2pb rgb(200,100,100), stop:%3pa rgb(100,200,100), stop:%3pb rgb(100,200,100), stop:%4pa rgb(230, 230, 230), stop:%4pb rgb(230, 230, 230), stop:%5p white);\nborder: 1px solid black;\nborder-radius: 3px;}")

taskmanager_page::taskmanager_page(QWidget *parent, sysadm_client *core) : PageWidget(parent, core), ui(new Ui::taskmanager_ui){
  ui->setupUi(this);
  connect(ui->push_kill, SIGNAL(clicked()), this, SLOT(slot_kill_proc()) );
}

taskmanager_page::~taskmanager_page(){

}

//Initialize the CORE <-->Page connections
void taskmanager_page::setupCore(){
  connect(CORE, SIGNAL(newReply(QString, QString, QString, QJsonValue)), this, SLOT(ParseReply(QString, QString, QString, QJsonValue)) );
}

//Page embedded, go ahead and startup any core requests
void taskmanager_page::startPage(){
  //Let the main window know the name of this page
  emit ChangePageTitle( tr("Task Manager") );

  //Now run any CORE communications
  slotRequestProcInfo();
  slotRequestMemInfo();
  slotRequestCPUInfo();
  slotRequestCPUTempInfo();

  qDebug() << "Start page!";
}

// === PRIVATE SLOTS ===
void taskmanager_page::ParseReply(QString id, QString namesp, QString name, QJsonValue args){
  if( !id.startsWith("page_task_man_")){ return; }
 // qDebug() << "reply" << id;

  // Read in the PID list
  if ( id == "page_task_man_taskquery")
  {
    if ( ! args.isObject() )
      return;
    parsePIDS(args.toObject());
    QTimer::singleShot(refreshRate, this, SLOT(slotRequestProcInfo()) );
  }
  else if(id=="page_task_man_mem_check"){
    if(name!="error" && namesp!="error"){
      if(args.isObject() && args.toObject().contains("memorystats")){
        QJsonObject memO = args.toObject().value("memorystats").toObject();
	//qDebug() << "Got memory info:" << args << memO;
	int active, cache, freeM, inactive, wired; //MB
	active = cache = freeM = inactive = wired = 0;
	if(memO.contains("active")){ active = memO.value("active").toString().toInt(); }
	if(memO.contains("cache")){ cache = memO.value("cache").toString().toInt(); }
	if(memO.contains("free")){ freeM = memO.value("free").toString().toInt(); }
	if(memO.contains("inactive")){ inactive = memO.value("inactive").toString().toInt(); }
	if(memO.contains("wired")){ wired = memO.value("wired").toString().toInt(); }
	ShowMemInfo(active, cache, freeM, inactive, wired);
      }
    }
    QTimer::singleShot(refreshRate, this, SLOT(slotRequestMemInfo()) );
  }else if(id=="page_task_man_cpu_check" && name!="error" && namesp!="error" ){
    //CPU usage
    qDebug() << "Got CPU Usage:" << args;
    QTimer::singleShot(refreshRate, this, SLOT(slotRequestCPUInfo()) );
  }else if(id=="page_task_man_cputemp_check" && name!="error" && namesp!="error" ){
    //CPU Temperature
    qDebug() << "Got CPU Temps:" << args;
    QTimer::singleShot(refreshRate, this, SLOT(slotRequestCPUTempInfo()) );
  }
}

void taskmanager_page::parsePIDS(QJsonObject jsobj)
{
  //ui->taskWidget->clear();

  //qDebug() << "KEYS" << jsobj.keys();
  QStringList keys = jsobj.keys();
  if (keys.contains("message") ) {
    qDebug() << "MESSAGE" << jsobj.value("message").toString();
    return;
  }

  // Look for procinfo
  QJsonObject procobj = jsobj.value("procinfo").toObject();
  QStringList pids = procobj.keys();
  int doEvents = 0;
  for ( int i=0; i < pids.size(); i++ )
  {
    doEvents++;
    if ( doEvents > 50 ) {
      doEvents=0;
      QApplication::processEvents();
    }
    QString PID = pids.at(i);
    QJsonObject pidinfo = procobj.value(PID).toObject();

    // Check if we have this PID already
    QList<QTreeWidgetItem *> foundItems = ui->taskWidget->findItems(PID, Qt::MatchExactly, 0);
    if ( ! foundItems.isEmpty() )
    {
      foundItems.at(0)->setText(1, pidinfo.value("username").toString());
      foundItems.at(0)->setText(2, pidinfo.value("thr").toString());
      foundItems.at(0)->setText(3, pidinfo.value("pri").toString());
      foundItems.at(0)->setText(4, pidinfo.value("nice").toString());
      foundItems.at(0)->setText(5, pidinfo.value("size").toString());
      foundItems.at(0)->setText(6, pidinfo.value("res").toString());
      foundItems.at(0)->setText(7, pidinfo.value("state").toString());
      foundItems.at(0)->setText(8, pidinfo.value("cpu").toString());
      foundItems.at(0)->setText(9, pidinfo.value("time").toString());
      foundItems.at(0)->setText(10, pidinfo.value("wcpu").toString());
      foundItems.at(0)->setText(11, pidinfo.value("command").toString());
    } else {
      // Create the new taskWidget item
      new QTreeWidgetItem(ui->taskWidget, QStringList() << PID
          << pidinfo.value("username").toString()
          << pidinfo.value("thr").toString()
          << pidinfo.value("pri").toString()
          << pidinfo.value("nice").toString()
          << pidinfo.value("size").toString()
          << pidinfo.value("res").toString()
          << pidinfo.value("state").toString()
          << pidinfo.value("cpu").toString()
          << pidinfo.value("time").toString()
          << pidinfo.value("wcpu").toString()
          << pidinfo.value("command").toString()
          );
    }
  }

  // Now loop through the UI and look for pids to remove
  for ( int i=0; i<ui->taskWidget->topLevelItemCount(); i++ ) {
    // Check if this item exists in the PID list
    if ( ! pids.contains(ui->taskWidget->topLevelItem(i)->text(0)) ) {
      // No? Remove it
      ui->taskWidget->takeTopLevelItem(i);
    }
  }

  // Resize the widget to the new contents
  ui->taskWidget->header()->resizeSections(QHeaderView::ResizeToContents);
  ui->taskWidget->sortItems(10, Qt::DescendingOrder);
}

void taskmanager_page::ShowMemInfo(int active, int cache, int freeM, int inactive, int wired){
  //assemble the stylesheet
  int total = active+cache+freeM+inactive+wired;
  QString style = memStyle;
  QString TT = tr("Memory Stats (MB)")+"\n";
    TT.append( QString(tr(" - Total: %1")).arg(QString::number(total))+"\n");
  // Wired memory
  double perc = qRound( 10000.0* (wired/( (double) total)) )/10000.0;
  double laststop = 0;
    TT.append( QString(tr(" - Wired: %1 (%2)")).arg(QString::number(wired), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%1p",QString::number(perc)); //placement
    style.replace("%2pa",QString::number(perc+0.00001)); //start of next section
    laststop = perc+0.00001;
  double totperc = perc;
  //Active memory
  perc = qRound( 10000.0* (active/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Active: %1 (%2)")).arg(QString::number(active), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%2pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%3pa",QString::number(totperc+0.00001)); //start of next section
    laststop = totperc+0.00001;
  //cache memory
  perc = qRound( 10000.0* (cache/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Cache: %1 (%2)")).arg(QString::number(cache), QString::number(perc*100.0)+"%")+"\n" );
    style.replace("%3pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%4pa",QString::number(totperc+0.0001) ); //start of next section
    laststop = totperc+0.0001;
  ui->label_mem_stats->setText( QString(tr("Total Memory: %1 MB,   Used: %2%")).arg(QString::number(total), QString::number(totperc*100.0)) );
  //inactive memory
  perc = qRound( 10000.0* (inactive/( (double) total)) )/10000.0;
  totperc+=perc;
    TT.append( QString(tr(" - Inactive: %1 (%2)")).arg(QString::number(inactive), QString::number(perc*100.0)+"%") +"\n");
    style.replace("%4pb",QString::number( (totperc>laststop) ? totperc : (laststop+0.000001) ));
    style.replace("%5p",QString::number(totperc+0.00001)); //start of next section
  //free memory
    TT.append( QString(tr(" - Free: %1 (%2)")).arg(QString::number(freeM), QString::number((1-totperc)*100.0)+"%") );
  //Now set the widgets
  //qDebug() << "styleSheet:" << style;
  ui->label_mem_stats->setToolTip(TT);
  ui->label_mem_stats->setStyleSheet(style);
}

void taskmanager_page::slotRequestProcInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "procinfo");
  CORE->communicate("page_task_man_taskquery", "sysadm", "systemmanager", jsobj);
}

void taskmanager_page::slotRequestMemInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "memorystats");
  CORE->communicate("page_task_man_mem_check", "sysadm", "systemmanager", jsobj);
}

void taskmanager_page::slotRequestCPUInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "cpupercentage");
  CORE->communicate("page_task_man_cpu_check", "sysadm", "systemmanager", jsobj);
}

void taskmanager_page::slotRequestCPUTempInfo(){
  QJsonObject jsobj;
  jsobj.insert("action", "cputemps");
  CORE->communicate("page_task_man_cputemp_check", "sysadm", "systemmanager", jsobj);
}

void taskmanager_page::slot_kill_proc(){
  //get the currently-selected PID
  QTreeWidgetItem *tmp = ui->taskWidget->currentItem();
  if(tmp==0){ return; }
  QString pid = tmp->text(0); //column 0 is the PID
  //Now send the request
  QJsonObject jsobj;
  jsobj.insert("action", "killproc");
  jsobj.insert("pid",pid);
  jsobj.insert("signal","KILL");
  CORE->communicate("page_task_man_kill_proc", "sysadm", "systemmanager", jsobj);
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: AccessiblePageHeaderArea.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: sab $ $Date: 2002-11-27 14:21:16 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_GEN_HXX
#include <tools/gen.hxx>
#endif

#ifndef _SC_ACCESSIBLEPAGEHEADERAREA_HXX
#include "AccessiblePageHeaderArea.hxx"
#endif
#ifndef _SC_ACCESSIBLETEXT_HXX
#include "AccessibleText.hxx"
#endif
#ifndef SC_ACCESSIBILITYHINTS_HXX
#include "AccessibilityHints.hxx"
#endif
#ifndef SC_UNOGUARD_HXX
#include "unoguard.hxx"
#endif
#ifndef SC_EDITSRC_HXX
#include "editsrc.hxx"
#endif
#include "prevwsh.hxx"
#include "prevloc.hxx"
#ifndef SC_SCRESID_HXX
#include "scresid.hxx"
#endif
#ifndef SC_SC_HRC
#include "sc.hrc"
#endif

#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleRole.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleStateType.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif

#ifndef _EDITOBJ_HXX
#include <svx/editobj.hxx>
#endif
#ifndef _SVX_ACCESSILE_TEXT_HELPER_HXX_
#include <svx/AccessibleTextHelper.hxx>
#endif
#ifndef _RTL_UUID_H_
#include <rtl/uuid.h>
#endif
#ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX_
#include <unotools/accessiblestatesethelper.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif
#ifndef _TOOLKIT_HELPER_CONVERT_HXX_
#include <toolkit/helper/convert.hxx>
#endif

using namespace ::com::sun::star;
using namespace ::drafts::com::sun::star::accessibility;

    //=====  internal  ========================================================

ScAccessiblePageHeaderArea::ScAccessiblePageHeaderArea(
        const uno::Reference<XAccessible>& rxParent,
        ScPreviewShell* pViewShell,
        const EditTextObject* pEditObj,
        sal_Bool bHeader,
        SvxAdjust eAdjust)
        : ScAccessibleContextBase(rxParent, AccessibleRole::TEXT),
        mpEditObj(pEditObj->Clone()),
        mpTextHelper(NULL),
        mpViewShell(pViewShell),
        mbHeader(bHeader),
        meAdjust(eAdjust)
{
    if (mpViewShell)
        mpViewShell->AddAccessibilityObject(*this);
}

ScAccessiblePageHeaderArea::~ScAccessiblePageHeaderArea(void)
{
    if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
    {
        // increment refcount to prevent double call off dtor
        osl_incrementInterlockedCount( &m_refCount );
        dispose();
    }
}

void SAL_CALL ScAccessiblePageHeaderArea::disposing()
{
    ScUnoGuard aGuard;
    if (mpViewShell)
    {
        mpViewShell->RemoveAccessibilityObject(*this);
        mpViewShell = NULL;
    }
    if (mpTextHelper)
        DELETEZ(mpTextHelper);
    if (mpEditObj)
        DELETEZ(mpEditObj);

    ScAccessibleContextBase::disposing();
}

//=====  SfxListener  =====================================================

void ScAccessiblePageHeaderArea::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    if (rHint.ISA( SfxSimpleHint ) )
    {
        const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
        // only notify if child exist, otherwise it is not necessary
        if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
        {
            if (mpTextHelper)
                mpTextHelper->UpdateChildren();

            AccessibleEventObject aEvent;
            aEvent.EventId = AccessibleEventId::ACCESSIBLE_VISIBLE_DATA_EVENT;
            aEvent.Source = uno::Reference< XAccessible >(this);
            CommitChange(aEvent);
        }
    }
    ScAccessibleContextBase::Notify(rBC, rHint);
}
    //=====  XAccessibleComponent  ============================================

uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeaderArea::getAccessibleAt(
        const awt::Point& rPoint )
        throw (uno::RuntimeException)
{
    uno::Reference<XAccessible> xRet;
    if (contains(rPoint))
    {
         ScUnoGuard aGuard;
        IsObjectValid();

        if(!mpTextHelper)
            CreateTextHelper();

        xRet = mpTextHelper->GetAt(rPoint);
    }

    return xRet;
}

    //=====  XAccessibleContext  ==============================================

sal_Int32 SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleChildCount(void)
                    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    if (!mpTextHelper)
        CreateTextHelper();
    return mpTextHelper->GetChildCount();
}

uno::Reference< XAccessible > SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleChild(sal_Int32 nIndex)
        throw (uno::RuntimeException,
        lang::IndexOutOfBoundsException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    if (!mpTextHelper)
        CreateTextHelper();
    return mpTextHelper->GetChild(nIndex);
}

uno::Reference<XAccessibleStateSet> SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleStateSet(void)
    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    uno::Reference<XAccessibleStateSet> xParentStates;
    if (getAccessibleParent().is())
    {
        uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
        xParentStates = xParentContext->getAccessibleStateSet();
    }
    utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
    if (IsDefunc())
        pStateSet->AddState(AccessibleStateType::DEFUNC);
    else
    {
        pStateSet->AddState(AccessibleStateType::ENABLED);
        pStateSet->AddState(AccessibleStateType::MULTILINE);
        if (isShowing())
            pStateSet->AddState(AccessibleStateType::SHOWING);
        if (isVisible())
            pStateSet->AddState(AccessibleStateType::VISIBLE);
    }
    return pStateSet;
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
       ScAccessiblePageHeaderArea::getImplementationName(void)
    throw (uno::RuntimeException)
{
    return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessiblePageHeaderArea"));
}

uno::Sequence< ::rtl::OUString> SAL_CALL
       ScAccessiblePageHeaderArea::getSupportedServiceNames(void)
    throw (uno::RuntimeException)
{
    uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
    sal_Int32 nOldSize(aSequence.getLength());
    aSequence.realloc(nOldSize + 1);
    ::rtl::OUString* pNames = aSequence.getArray();

    pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("drafts.com.sun.star.sheet.AccessiblePageHeaderFooterAreasView"));

    return aSequence;
}

//=====  XTypeProvider  =======================================================

uno::Sequence<sal_Int8> SAL_CALL
    ScAccessiblePageHeaderArea::getImplementationId(void)
    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    static uno::Sequence<sal_Int8> aId;
    if (aId.getLength() == 0)
    {
        aId.realloc (16);
        rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
    }
    return aId;
}

//===== internal ==============================================================
rtl::OUString SAL_CALL ScAccessiblePageHeaderArea::createAccessibleDescription(void)
    throw(uno::RuntimeException)
{
    rtl::OUString sDesc;
    switch (meAdjust)
    {
    case SVX_ADJUST_LEFT :
        sDesc = String(ScResId(STR_ACC_LEFTAREA_DESCR));
        break;
    case SVX_ADJUST_RIGHT:
        sDesc = String(ScResId(STR_ACC_RIGHTAREA_DESCR));
        break;
    case SVX_ADJUST_CENTER:
        sDesc = String(ScResId(STR_ACC_CENTERAREA_DESCR));
        break;
    default:
        DBG_ERRORFILE("wrong adjustment found");
    }

    return sDesc;
}

rtl::OUString SAL_CALL ScAccessiblePageHeaderArea::createAccessibleName(void)
    throw (uno::RuntimeException)
{
    rtl::OUString sName;
    switch (meAdjust)
    {
    case SVX_ADJUST_LEFT :
        sName = String(ScResId(STR_ACC_LEFTAREA_NAME));
        break;
    case SVX_ADJUST_RIGHT:
        sName = String(ScResId(STR_ACC_RIGHTAREA_NAME));
        break;
    case SVX_ADJUST_CENTER:
        sName = String(ScResId(STR_ACC_CENTERAREA_NAME));
        break;
    default:
        DBG_ERRORFILE("wrong adjustment found");
    }

    return sName;
}

Rectangle ScAccessiblePageHeaderArea::GetBoundingBoxOnScreen(void) const
    throw(::com::sun::star::uno::RuntimeException)
{
    Rectangle aRect;
    if (mxParent.is())
    {
        uno::Reference<XAccessibleContext> xContext = mxParent->getAccessibleContext();
        uno::Reference<XAccessibleComponent> xComp(xContext, uno::UNO_QUERY);
        if (xComp.is())
        {
            // has the same size and position on screen like the parent
            aRect = Rectangle(VCLPoint(xComp->getLocationOnScreen()), VCLRectangle(xComp->getBounds()).GetSize());
        }
    }
    return aRect;
}

Rectangle ScAccessiblePageHeaderArea::GetBoundingBox(void) const
    throw (::com::sun::star::uno::RuntimeException)
{
    Rectangle aRect;
    if (mxParent.is())
    {
        uno::Reference<XAccessibleContext> xContext = mxParent->getAccessibleContext();
        uno::Reference<XAccessibleComponent> xComp(xContext, uno::UNO_QUERY);
        if (xComp.is())
        {
            // has the same size and position on screen like the parent and so the pos is (0, 0)
            Rectangle aNewRect(Point(0, 0), VCLRectangle(xComp->getBounds()).GetSize());
            aRect = aNewRect;
        }
    }

    return aRect;
}

void ScAccessiblePageHeaderArea::CreateTextHelper()
{
    if (!mpTextHelper)
    {
        ::std::auto_ptr < ScAccessibleTextData > pAccessibleHeaderTextData
            (new ScAccessibleHeaderTextData(mpViewShell, mpEditObj, mbHeader, meAdjust));
        ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleHeaderTextData));

        mpTextHelper = new accessibility::AccessibleTextHelper(pEditSource );
        mpTextHelper->SetEventSource(this);
    }
}
<commit_msg>INTEGRATION: CWS uaa02 (1.14.128); FILE MERGED 2003/04/22 08:14:50 mt 1.14.128.1: #108656# Moved Accessibility from drafts to final<commit_after>/*************************************************************************
 *
 *  $RCSfile: AccessiblePageHeaderArea.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: vg $ $Date: 2003-04-24 17:11:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _SV_GEN_HXX
#include <tools/gen.hxx>
#endif

#ifndef _SC_ACCESSIBLEPAGEHEADERAREA_HXX
#include "AccessiblePageHeaderArea.hxx"
#endif
#ifndef _SC_ACCESSIBLETEXT_HXX
#include "AccessibleText.hxx"
#endif
#ifndef SC_ACCESSIBILITYHINTS_HXX
#include "AccessibilityHints.hxx"
#endif
#ifndef SC_UNOGUARD_HXX
#include "unoguard.hxx"
#endif
#ifndef SC_EDITSRC_HXX
#include "editsrc.hxx"
#endif
#include "prevwsh.hxx"
#include "prevloc.hxx"
#ifndef SC_SCRESID_HXX
#include "scresid.hxx"
#endif
#ifndef SC_SC_HRC
#include "sc.hrc"
#endif

#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLEROLE_HPP_
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESTATETYPE_HPP_
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#endif
#ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
#include <com/sun/star/accessibility/AccessibleEventId.hpp>
#endif

#ifndef _EDITOBJ_HXX
#include <svx/editobj.hxx>
#endif
#ifndef _SVX_ACCESSILE_TEXT_HELPER_HXX_
#include <svx/AccessibleTextHelper.hxx>
#endif
#ifndef _RTL_UUID_H_
#include <rtl/uuid.h>
#endif
#ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX_
#include <unotools/accessiblestatesethelper.hxx>
#endif
#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif
#ifndef _TOOLKIT_HELPER_CONVERT_HXX_
#include <toolkit/helper/convert.hxx>
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::accessibility;

    //=====  internal  ========================================================

ScAccessiblePageHeaderArea::ScAccessiblePageHeaderArea(
        const uno::Reference<XAccessible>& rxParent,
        ScPreviewShell* pViewShell,
        const EditTextObject* pEditObj,
        sal_Bool bHeader,
        SvxAdjust eAdjust)
        : ScAccessibleContextBase(rxParent, AccessibleRole::TEXT),
        mpEditObj(pEditObj->Clone()),
        mpTextHelper(NULL),
        mpViewShell(pViewShell),
        mbHeader(bHeader),
        meAdjust(eAdjust)
{
    if (mpViewShell)
        mpViewShell->AddAccessibilityObject(*this);
}

ScAccessiblePageHeaderArea::~ScAccessiblePageHeaderArea(void)
{
    if (!ScAccessibleContextBase::IsDefunc() && !rBHelper.bInDispose)
    {
        // increment refcount to prevent double call off dtor
        osl_incrementInterlockedCount( &m_refCount );
        dispose();
    }
}

void SAL_CALL ScAccessiblePageHeaderArea::disposing()
{
    ScUnoGuard aGuard;
    if (mpViewShell)
    {
        mpViewShell->RemoveAccessibilityObject(*this);
        mpViewShell = NULL;
    }
    if (mpTextHelper)
        DELETEZ(mpTextHelper);
    if (mpEditObj)
        DELETEZ(mpEditObj);

    ScAccessibleContextBase::disposing();
}

//=====  SfxListener  =====================================================

void ScAccessiblePageHeaderArea::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
{
    if (rHint.ISA( SfxSimpleHint ) )
    {
        const SfxSimpleHint& rRef = (const SfxSimpleHint&)rHint;
        // only notify if child exist, otherwise it is not necessary
        if (rRef.GetId() == SC_HINT_ACC_VISAREACHANGED)
        {
            if (mpTextHelper)
                mpTextHelper->UpdateChildren();

            AccessibleEventObject aEvent;
            aEvent.EventId = AccessibleEventId::VISIBLE_DATA_CHANGED;
            aEvent.Source = uno::Reference< XAccessible >(this);
            CommitChange(aEvent);
        }
    }
    ScAccessibleContextBase::Notify(rBC, rHint);
}
    //=====  XAccessibleComponent  ============================================

uno::Reference< XAccessible > SAL_CALL ScAccessiblePageHeaderArea::getAccessibleAtPoint(
        const awt::Point& rPoint )
        throw (uno::RuntimeException)
{
    uno::Reference<XAccessible> xRet;
    if (containsPoint(rPoint))
    {
         ScUnoGuard aGuard;
        IsObjectValid();

        if(!mpTextHelper)
            CreateTextHelper();

        xRet = mpTextHelper->GetAt(rPoint);
    }

    return xRet;
}

    //=====  XAccessibleContext  ==============================================

sal_Int32 SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleChildCount(void)
                    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    if (!mpTextHelper)
        CreateTextHelper();
    return mpTextHelper->GetChildCount();
}

uno::Reference< XAccessible > SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleChild(sal_Int32 nIndex)
        throw (uno::RuntimeException,
        lang::IndexOutOfBoundsException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    if (!mpTextHelper)
        CreateTextHelper();
    return mpTextHelper->GetChild(nIndex);
}

uno::Reference<XAccessibleStateSet> SAL_CALL
    ScAccessiblePageHeaderArea::getAccessibleStateSet(void)
    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    uno::Reference<XAccessibleStateSet> xParentStates;
    if (getAccessibleParent().is())
    {
        uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
        xParentStates = xParentContext->getAccessibleStateSet();
    }
    utl::AccessibleStateSetHelper* pStateSet = new utl::AccessibleStateSetHelper();
    if (IsDefunc())
        pStateSet->AddState(AccessibleStateType::DEFUNC);
    else
    {
        pStateSet->AddState(AccessibleStateType::ENABLED);
        pStateSet->AddState(AccessibleStateType::MULTI_LINE);
        if (isShowing())
            pStateSet->AddState(AccessibleStateType::SHOWING);
        if (isVisible())
            pStateSet->AddState(AccessibleStateType::VISIBLE);
    }
    return pStateSet;
}

//=====  XServiceInfo  ========================================================

::rtl::OUString SAL_CALL
       ScAccessiblePageHeaderArea::getImplementationName(void)
    throw (uno::RuntimeException)
{
    return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("ScAccessiblePageHeaderArea"));
}

uno::Sequence< ::rtl::OUString> SAL_CALL
       ScAccessiblePageHeaderArea::getSupportedServiceNames(void)
    throw (uno::RuntimeException)
{
    uno::Sequence< ::rtl::OUString > aSequence = ScAccessibleContextBase::getSupportedServiceNames();
    sal_Int32 nOldSize(aSequence.getLength());
    aSequence.realloc(nOldSize + 1);
    ::rtl::OUString* pNames = aSequence.getArray();

    pNames[nOldSize] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.AccessiblePageHeaderFooterAreasView"));

    return aSequence;
}

//=====  XTypeProvider  =======================================================

uno::Sequence<sal_Int8> SAL_CALL
    ScAccessiblePageHeaderArea::getImplementationId(void)
    throw (uno::RuntimeException)
{
    ScUnoGuard aGuard;
    IsObjectValid();
    static uno::Sequence<sal_Int8> aId;
    if (aId.getLength() == 0)
    {
        aId.realloc (16);
        rtl_createUuid (reinterpret_cast<sal_uInt8 *>(aId.getArray()), 0, sal_True);
    }
    return aId;
}

//===== internal ==============================================================
rtl::OUString SAL_CALL ScAccessiblePageHeaderArea::createAccessibleDescription(void)
    throw(uno::RuntimeException)
{
    rtl::OUString sDesc;
    switch (meAdjust)
    {
    case SVX_ADJUST_LEFT :
        sDesc = String(ScResId(STR_ACC_LEFTAREA_DESCR));
        break;
    case SVX_ADJUST_RIGHT:
        sDesc = String(ScResId(STR_ACC_RIGHTAREA_DESCR));
        break;
    case SVX_ADJUST_CENTER:
        sDesc = String(ScResId(STR_ACC_CENTERAREA_DESCR));
        break;
    default:
        DBG_ERRORFILE("wrong adjustment found");
    }

    return sDesc;
}

rtl::OUString SAL_CALL ScAccessiblePageHeaderArea::createAccessibleName(void)
    throw (uno::RuntimeException)
{
    rtl::OUString sName;
    switch (meAdjust)
    {
    case SVX_ADJUST_LEFT :
        sName = String(ScResId(STR_ACC_LEFTAREA_NAME));
        break;
    case SVX_ADJUST_RIGHT:
        sName = String(ScResId(STR_ACC_RIGHTAREA_NAME));
        break;
    case SVX_ADJUST_CENTER:
        sName = String(ScResId(STR_ACC_CENTERAREA_NAME));
        break;
    default:
        DBG_ERRORFILE("wrong adjustment found");
    }

    return sName;
}

Rectangle ScAccessiblePageHeaderArea::GetBoundingBoxOnScreen(void) const
    throw(::com::sun::star::uno::RuntimeException)
{
    Rectangle aRect;
    if (mxParent.is())
    {
        uno::Reference<XAccessibleContext> xContext = mxParent->getAccessibleContext();
        uno::Reference<XAccessibleComponent> xComp(xContext, uno::UNO_QUERY);
        if (xComp.is())
        {
            // has the same size and position on screen like the parent
            aRect = Rectangle(VCLPoint(xComp->getLocationOnScreen()), VCLRectangle(xComp->getBounds()).GetSize());
        }
    }
    return aRect;
}

Rectangle ScAccessiblePageHeaderArea::GetBoundingBox(void) const
    throw (::com::sun::star::uno::RuntimeException)
{
    Rectangle aRect;
    if (mxParent.is())
    {
        uno::Reference<XAccessibleContext> xContext = mxParent->getAccessibleContext();
        uno::Reference<XAccessibleComponent> xComp(xContext, uno::UNO_QUERY);
        if (xComp.is())
        {
            // has the same size and position on screen like the parent and so the pos is (0, 0)
            Rectangle aNewRect(Point(0, 0), VCLRectangle(xComp->getBounds()).GetSize());
            aRect = aNewRect;
        }
    }

    return aRect;
}

void ScAccessiblePageHeaderArea::CreateTextHelper()
{
    if (!mpTextHelper)
    {
        ::std::auto_ptr < ScAccessibleTextData > pAccessibleHeaderTextData
            (new ScAccessibleHeaderTextData(mpViewShell, mpEditObj, mbHeader, meAdjust));
        ::std::auto_ptr< SvxEditSource > pEditSource (new ScAccessibilityEditSource(pAccessibleHeaderTextData));

        mpTextHelper = new ::accessibility::AccessibleTextHelper(pEditSource );
        mpTextHelper->SetEventSource(this);
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <ctime>

#include <rapidjson/document.h>
#include <picojson.h>
#include <rabbit.hpp>

void print(int score, const std::string& title, const std::string& url)
{
  std::cerr << "(" << score << ") " << title << " - " << url << std::endl;
}

template <typename Bench>
struct runner
{
  Bench bench;
  std::string json;
  int score;
  int try_count;

  runner()
    : score(0)
    , try_count(0)
  {
    std::ifstream ifs("hot.json");
    std::istreambuf_iterator<char> it(ifs), last;
    json = std::string(it, last);
  }

  void run(int n)
  {
    try
    {
      std::clock_t t = std::clock();

      while (n-- > 0)
        bench(json);

      score += (std::clock() - t);
    }
    catch (std::exception& e)
    {
      std::cout << e.what() << std::endl;
    }

    ++try_count;
  }

  void disp() const
  {
    std::cout << bench.name() << " " << "score: " << (score / try_count) << std::endl;
  }
};

struct rapidjson_bench
{
  std::string name() const { return "rapidjson"; }
  void operator()(const std::string& json) const
  {
    rapidjson::Document doc;
    if (doc.Parse<0>(json.c_str()).HasParseError())
      throw std::runtime_error("parse_error");

    const rapidjson::Value& children = doc["data"]["children"];
    for (rapidjson::Value::ConstValueIterator it = children.Begin(); it != children.End(); ++it)
    {
      const rapidjson::Value& data = (*it)["data"];
      print(data["score"].GetInt(), data["title"].GetString(), data["url"].GetString());
    }
  }
};

struct picojson_bench
{
  std::string name() const { return "picojson"; }
  void operator()(const std::string& json) const
  {
    picojson::value v;
    std::string error;
    std::string::const_iterator it = json.begin();
    picojson::parse(v, it, json.end(), &error);
    if (!error.empty())
      throw std::runtime_error(error);

    const picojson::array& children = v.get("data").get("children").get<picojson::array>();
    for (picojson::array::const_iterator it = children.begin(); it != children.end(); ++it)
    {
      const picojson::value& data = it->get("data");
      print(data.get("score").get<double>(), data.get("title").get<std::string>(), data.get("url").get<std::string>());
    }
  }
};

struct rabbit_bench
{
  std::string name() const { return "rabbit"; }
  void operator()(const std::string& json) const
  {
    rabbit::document doc;
    try { doc.parse(json); } catch (...) { throw; }

    rabbit::const_array children = doc["data"]["children"];
    for (rabbit::array::const_iterator it = children.begin(); it != children.end(); ++it)
    {
      rabbit::const_object data = it->cat("data");
      print(data["score"].as(), data["title"].as(), data["url"].as());
    }
  }
};

int main(int argc, char** argv)
{
  int n = 1000;
  int m = 5;
  if (argc >= 2) n = std::atoi(argv[1]);
  if (argc >= 3) m = std::atoi(argv[2]);

  runner<rapidjson_bench> r1;
  runner<picojson_bench> r2;
  runner<rabbit_bench> r3;

  for (int i = 1; i <= m; ++i)
  {
    std::cout << i << "/" << m << " trying...";
    r1.run(n);
    r2.run(n);
    r3.run(n);
    std::cout << "OK" << std::endl;
  }

  r1.disp();
  r2.disp();
  r3.disp();
}

<commit_msg>fix bench<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <stdexcept>
#include <cstdlib>
#include <ctime>

#include <rapidjson/document.h>
#include <picojson.h>
#include <rabbit.hpp>

void print(int score, const std::string& title, const std::string& url)
{
  std::cerr << "(" << score << ") " << title << " - " << url << std::endl;
}

template <typename Bench>
struct runner
{
  Bench bench;
  std::string json;
  int score;
  int try_count;

  runner(const std::string& json)
    : json(json)
    , score(0)
    , try_count(0)
  {}

  void run(int n)
  {
    try
    {
      std::clock_t t = std::clock();

      while (n-- > 0)
        bench(json);

      score += (std::clock() - t);
    }
    catch (std::exception& e)
    {
      std::cout << e.what() << std::endl;
    }

    ++try_count;
  }

  void disp() const
  {
    std::cout << bench.name() << " " << "score: " << (score / try_count) << std::endl;
  }
};

struct rapidjson_bench
{
  std::string name() const { return "rapidjson"; }
  void operator()(const std::string& json) const
  {
    rapidjson::Document doc;
    if (doc.Parse<0>(json.c_str()).HasParseError())
      throw std::runtime_error("parse_error");

    const rapidjson::Value& children = doc["data"]["children"];
    for (rapidjson::Value::ConstValueIterator it = children.Begin(); it != children.End(); ++it)
    {
      const rapidjson::Value& data = (*it)["data"];
      print(data["score"].GetInt(), data["title"].GetString(), data["url"].GetString());
    }
  }
};

struct picojson_bench
{
  std::string name() const { return "picojson "; }
  void operator()(const std::string& json) const
  {
    picojson::value v;
    std::string error;
    std::string::const_iterator it = json.begin();
    picojson::parse(v, it, json.end(), &error);
    if (!error.empty())
      throw std::runtime_error(error);

    const picojson::array& children = v.get("data").get("children").get<picojson::array>();
    for (picojson::array::const_iterator it = children.begin(); it != children.end(); ++it)
    {
      const picojson::value& data = it->get("data");
      print(data.get("score").get<double>(), data.get("title").get<std::string>(), data.get("url").get<std::string>());
    }
  }
};

struct rabbit_bench
{
  std::string name() const { return "rabbit   "; }
  void operator()(const std::string& json) const
  {
    rabbit::document doc;
    try { doc.parse(json); } catch (...) { throw; }

    rabbit::const_array children = doc["data"]["children"];
    for (rabbit::array::const_iterator it = children.begin(); it != children.end(); ++it)
    {
      rabbit::const_object data = it->cat("data");
      print(data["score"].as(), data["title"].as(), data["url"].as());
    }
  }
};

int main(int argc, char** argv)
{
  int n = 1000;
  if (argc >= 2) n = std::atoi(argv[1]);

  std::ifstream ifs("hot.json");
  std::istreambuf_iterator<char> it(ifs), last;
  std::string json = std::string(it, last);

  runner<rapidjson_bench> r1(json);
  runner<picojson_bench> r2(json);
  runner<rabbit_bench> r3(json);

  int i = 1;
  while (true)
  {
    std::cout << i << " trying...";
    r1.run(n);
    r2.run(n);
    r3.run(n);
    std::cout << "OK" << std::endl;

    r1.disp();
    r2.disp();
    r3.disp();

    std::cout << "---" << std::endl;
    ++i;
  }
}

<|endoftext|>


<commit_before>#include <set>

#define NOD_ATHENA 1
#include "DNAMP3.hpp"
#include "STRG.hpp"
#include "MLVL.hpp"
#include "CAUD.hpp"
#include "CMDL.hpp"
#include "CHAR.hpp"
#include "MREA.hpp"
#include "MAPA.hpp"
#include "SAVW.hpp"
#include "HINT.hpp"
#include "DataSpec/DNACommon/TXTR.hpp"
#include "DataSpec/DNACommon/FONT.hpp"
#include "DataSpec/DNACommon/FSM2.hpp"
#include "DataSpec/DNACommon/DGRP.hpp"
#include "Runtime/GCNTypes.hpp"

namespace DataSpec::DNAMP3 {
logvisor::Module Log("urde::DNAMP3");

static bool GetNoShare(std::string_view name) {
  std::string lowerName(name);
  std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
  if (!lowerName.compare(0, 7, "metroid"))
    return false;
  return true;
}

PAKBridge::PAKBridge(const nod::Node& node, bool doExtract)
: m_node(node), m_pak(GetNoShare(node.getName())), m_doExtract(doExtract) {
  nod::AthenaPartReadStream rs(node.beginReadStream());
  m_pak.read(rs);

  /* Append Level String */
  std::set<hecl::SystemString, hecl::CaseInsensitiveCompare> uniq;
  for (auto& ent : m_pak.m_entries) {
    PAK::Entry& entry = ent.second;
    if (entry.type == FOURCC('MLVL')) {
      PAKEntryReadStream rs = entry.beginReadStream(m_node);
      MLVL mlvl;
      mlvl.read(rs);
      const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId);
      if (nameEnt) {
        PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
        STRG mlvlName;
        mlvlName.read(rs);
        uniq.insert(mlvlName.getSystemString(FOURCC('ENGL'), 0));
      }
    }
  }
  bool comma = false;
  for (const hecl::SystemString& str : uniq) {
    if (comma)
      m_levelString += _SYS_STR(", ");
    comma = true;
    m_levelString += str;
  }
}

static hecl::SystemString LayerName(std::string_view name) {
  hecl::SystemString ret(hecl::SystemStringConv(name).sys_str());
  for (auto& ch : ret)
    if (ch == _SYS_STR('/') || ch == _SYS_STR('\\'))
      ch = _SYS_STR('-');
  return ret;
}

void PAKBridge::build() {
  /* First pass: build per-area/per-layer dependency map */
  for (const auto& ent : m_pak.m_entries) {
    const PAK::Entry& entry = ent.second;
    if (entry.type == FOURCC('MLVL')) {
      Level& level = m_levelDeps[entry.id];

      MLVL mlvl;
      {
        PAKEntryReadStream rs = entry.beginReadStream(m_node);
        mlvl.read(rs);
      }
      std::string catalogueName;
      std::string bestName = m_pak.bestEntryName(m_node, entry, catalogueName);
      level.name = hecl::SystemStringConv(bestName).sys_str();
      level.areas.reserve(mlvl.areaCount);
      unsigned layerIdx = 0;

      /* Make MAPW available to lookup MAPAs */
      const PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap);
      std::vector<UniqueID64> mapw;
      if (worldMapEnt) {
        PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node);
        rs.seek(8, athena::SeekOrigin::Current);
        atUint32 areaCount = rs.readUint32Big();
        mapw.reserve(areaCount);
        for (atUint32 i = 0; i < areaCount; ++i)
          mapw.emplace_back(rs);
      }

      /* Index areas */
      unsigned ai = 0;
      auto layerFlagsIt = mlvl.layerFlags.begin();
      for (const MLVL::Area& area : mlvl.areas) {
        Level::Area& areaDeps = level.areas[area.areaMREAId];
        const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
        if (areaNameEnt) {
          STRG areaName;
          {
            PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
            areaName.read(rs);
          }
          areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
          areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
        }
        if (areaDeps.name.empty()) {
          areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str();
          if (areaDeps.name.empty()) {
            std::string idStr = area.areaMREAId.toString();
            areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
          }
        }
        hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai);
        areaDeps.name = num + areaDeps.name;

        const MLVL::LayerFlags& layerFlags = *layerFlagsIt++;
        if (layerFlags.layerCount) {
          areaDeps.layers.reserve(layerFlags.layerCount);
          for (unsigned l = 1; l < layerFlags.layerCount; ++l) {
            areaDeps.layers.emplace_back();
            Level::Area::Layer& layer = areaDeps.layers.back();
            layer.name = LayerName(mlvl.layerNames[layerIdx++]);
            layer.active = layerFlags.flags >> (l - 1) & 0x1;
            layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
            num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1);
            layer.name = num + layer.name;
          }
        }

        /* Load area DEPS */
        const PAK::Entry* areaEntry = m_pak.lookupEntry(area.areaMREAId);
        if (areaEntry) {
          PAKEntryReadStream ars = areaEntry->beginReadStream(m_node);
          MREA::ExtractLayerDeps(ars, areaDeps);
        }
        areaDeps.resources.emplace(area.areaMREAId);
        if (mapw.size() > ai)
          areaDeps.resources.emplace(mapw[ai]);
        ++ai;
      }
    }
  }

  /* Second pass: cross-compare uniqueness */
  for (auto& entry : m_pak.m_entries) {
    entry.second.unique.checkEntry(*this, entry.second);
  }
}

void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID64>& charAssoc) const {
  for (const std::pair<UniqueID64, PAK::Entry>& entry : m_pak.m_entries) {
    if (entry.second.type == FOURCC('CHAR')) {
      PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
      CHAR aChar;
      aChar.read(rs);
      const CHAR::CharacterInfo& ci = aChar.characterInfo;
      charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf};
      charAssoc.m_cskrToCharacter[ci.cskr] =
          std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr));
      for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) {
        charAssoc.m_cmdlRigs[overlay.cmdl] = {overlay.cskr, ci.cinf};
        charAssoc.m_cskrToCharacter[overlay.cskr] =
            std::make_pair(entry.second.id, fmt::format(fmt("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr));
      }
    }
  }
}

static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}};

void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
                                  std::unordered_map<UniqueID64, zeus::CMatrix4f>& addTo,
                                  std::unordered_map<UniqueID64, hecl::ProjectPath>& pathOverrides) const {
  for (const std::pair<UniqueID64, PAK::Entry>& entry : m_pak.m_entries) {
    if (entry.second.type == FOURCC('MLVL')) {
      MLVL mlvl;
      {
        PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
        mlvl.read(rs);
      }
      hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath();

      if (mlvl.worldNameId.isValid())
        pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
            fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));

      for (const MLVL::Area& area : mlvl.areas) {
        hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
        if (area.areaNameId.isValid())
          pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
              fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId));
      }

      if (mlvl.worldMap.isValid()) {
        const nod::Node* mapNode;
        const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
        if (mapEntry) {
          PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
          u32 magic = rs.readUint32Big();
          if (magic == 0xDEADF00D) {
            rs.readUint32Big();
            u32 count = rs.readUint32Big();
            for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) {
              MLVL::Area& areaData = mlvl.areas[i];
              UniqueID64 mapaId;
              mapaId.read(rs);
              addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1],
                                              areaData.transformMtx[2], BottomRow)
                                  .transposed();
            }
          }
        }
      }
    }
  }
}

ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) {
  switch (entry.type.toUint32()) {
  case SBIG('CAUD'):
    return {CAUD::Extract, {_SYS_STR(".yaml")}};
  case SBIG('STRG'):
    return {STRG::Extract, {_SYS_STR(".yaml")}};
  case SBIG('TXTR'):
    return {TXTR::Extract, {_SYS_STR(".png")}};
  case SBIG('SAVW'):
    return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
  case SBIG('HINT'):
    return {HINT::Extract, {_SYS_STR(".yaml")}};
//  case SBIG('CMDL'):
//    return {CMDL::Extract, {_SYS_STR(".blend")}, 1};
//  case SBIG('CHAR'):
//    return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
//  case SBIG('MLVL'):
//    return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
//  case SBIG('MREA'):
//    return {MREA::Extract, {_SYS_STR(".blend")}, 4};
//  case SBIG('MAPA'):
//    return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
  case SBIG('FSM2'):
    return {DNAFSM2::ExtractFSM2<UniqueID64>, {_SYS_STR(".yaml")}};
  case SBIG('FONT'):
    return {DNAFont::ExtractFONT<UniqueID64>, {_SYS_STR(".yaml")}};
  case SBIG('DGRP'):
    return {DNADGRP::ExtractDGRP<UniqueID64>, {_SYS_STR(".yaml")}};
  }
  return {};
}

} // namespace DataSpec::DNAMP3
<commit_msg>DNAMP3: Prevent unnecessary copies<commit_after>#include <set>

#define NOD_ATHENA 1
#include "DNAMP3.hpp"
#include "STRG.hpp"
#include "MLVL.hpp"
#include "CAUD.hpp"
#include "CMDL.hpp"
#include "CHAR.hpp"
#include "MREA.hpp"
#include "MAPA.hpp"
#include "SAVW.hpp"
#include "HINT.hpp"
#include "DataSpec/DNACommon/TXTR.hpp"
#include "DataSpec/DNACommon/FONT.hpp"
#include "DataSpec/DNACommon/FSM2.hpp"
#include "DataSpec/DNACommon/DGRP.hpp"
#include "Runtime/GCNTypes.hpp"

namespace DataSpec::DNAMP3 {
logvisor::Module Log("urde::DNAMP3");

static bool GetNoShare(std::string_view name) {
  std::string lowerName(name);
  std::transform(lowerName.begin(), lowerName.end(), lowerName.begin(), tolower);
  if (!lowerName.compare(0, 7, "metroid"))
    return false;
  return true;
}

PAKBridge::PAKBridge(const nod::Node& node, bool doExtract)
: m_node(node), m_pak(GetNoShare(node.getName())), m_doExtract(doExtract) {
  nod::AthenaPartReadStream rs(node.beginReadStream());
  m_pak.read(rs);

  /* Append Level String */
  std::set<hecl::SystemString, hecl::CaseInsensitiveCompare> uniq;
  for (auto& ent : m_pak.m_entries) {
    PAK::Entry& entry = ent.second;
    if (entry.type == FOURCC('MLVL')) {
      PAKEntryReadStream rs = entry.beginReadStream(m_node);
      MLVL mlvl;
      mlvl.read(rs);
      const PAK::Entry* nameEnt = m_pak.lookupEntry(mlvl.worldNameId);
      if (nameEnt) {
        PAKEntryReadStream rs = nameEnt->beginReadStream(m_node);
        STRG mlvlName;
        mlvlName.read(rs);
        uniq.insert(mlvlName.getSystemString(FOURCC('ENGL'), 0));
      }
    }
  }
  bool comma = false;
  for (const hecl::SystemString& str : uniq) {
    if (comma)
      m_levelString += _SYS_STR(", ");
    comma = true;
    m_levelString += str;
  }
}

static hecl::SystemString LayerName(std::string_view name) {
  hecl::SystemString ret(hecl::SystemStringConv(name).sys_str());
  for (auto& ch : ret)
    if (ch == _SYS_STR('/') || ch == _SYS_STR('\\'))
      ch = _SYS_STR('-');
  return ret;
}

void PAKBridge::build() {
  /* First pass: build per-area/per-layer dependency map */
  for (const auto& ent : m_pak.m_entries) {
    const PAK::Entry& entry = ent.second;
    if (entry.type == FOURCC('MLVL')) {
      Level& level = m_levelDeps[entry.id];

      MLVL mlvl;
      {
        PAKEntryReadStream rs = entry.beginReadStream(m_node);
        mlvl.read(rs);
      }
      std::string catalogueName;
      std::string bestName = m_pak.bestEntryName(m_node, entry, catalogueName);
      level.name = hecl::SystemStringConv(bestName).sys_str();
      level.areas.reserve(mlvl.areaCount);
      unsigned layerIdx = 0;

      /* Make MAPW available to lookup MAPAs */
      const PAK::Entry* worldMapEnt = m_pak.lookupEntry(mlvl.worldMap);
      std::vector<UniqueID64> mapw;
      if (worldMapEnt) {
        PAKEntryReadStream rs = worldMapEnt->beginReadStream(m_node);
        rs.seek(8, athena::SeekOrigin::Current);
        atUint32 areaCount = rs.readUint32Big();
        mapw.reserve(areaCount);
        for (atUint32 i = 0; i < areaCount; ++i)
          mapw.emplace_back(rs);
      }

      /* Index areas */
      unsigned ai = 0;
      auto layerFlagsIt = mlvl.layerFlags.begin();
      for (const MLVL::Area& area : mlvl.areas) {
        Level::Area& areaDeps = level.areas[area.areaMREAId];
        const PAK::Entry* areaNameEnt = m_pak.lookupEntry(area.areaNameId);
        if (areaNameEnt) {
          STRG areaName;
          {
            PAKEntryReadStream rs = areaNameEnt->beginReadStream(m_node);
            areaName.read(rs);
          }
          areaDeps.name = areaName.getSystemString(FOURCC('ENGL'), 0);
          areaDeps.name = hecl::StringUtils::TrimWhitespace(areaDeps.name);
        }
        if (areaDeps.name.empty()) {
          areaDeps.name = hecl::SystemStringConv(area.internalAreaName).sys_str();
          if (areaDeps.name.empty()) {
            std::string idStr = area.areaMREAId.toString();
            areaDeps.name = hecl::SystemString(_SYS_STR("MREA_")) + hecl::SystemStringConv(idStr).c_str();
          }
        }
        hecl::SystemString num = fmt::format(fmt(_SYS_STR("{:02d} ")), ai);
        areaDeps.name = num + areaDeps.name;

        const MLVL::LayerFlags& layerFlags = *layerFlagsIt++;
        if (layerFlags.layerCount) {
          areaDeps.layers.reserve(layerFlags.layerCount);
          for (unsigned l = 1; l < layerFlags.layerCount; ++l) {
            areaDeps.layers.emplace_back();
            Level::Area::Layer& layer = areaDeps.layers.back();
            layer.name = LayerName(mlvl.layerNames[layerIdx++]);
            layer.active = layerFlags.flags >> (l - 1) & 0x1;
            layer.name = hecl::StringUtils::TrimWhitespace(layer.name);
            num = fmt::format(fmt(_SYS_STR("{:02d} ")), l - 1);
            layer.name = num + layer.name;
          }
        }

        /* Load area DEPS */
        const PAK::Entry* areaEntry = m_pak.lookupEntry(area.areaMREAId);
        if (areaEntry) {
          PAKEntryReadStream ars = areaEntry->beginReadStream(m_node);
          MREA::ExtractLayerDeps(ars, areaDeps);
        }
        areaDeps.resources.emplace(area.areaMREAId);
        if (mapw.size() > ai)
          areaDeps.resources.emplace(mapw[ai]);
        ++ai;
      }
    }
  }

  /* Second pass: cross-compare uniqueness */
  for (auto& entry : m_pak.m_entries) {
    entry.second.unique.checkEntry(*this, entry.second);
  }
}

void PAKBridge::addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID64>& charAssoc) const {
  for (const auto& entry : m_pak.m_entries) {
    if (entry.second.type == FOURCC('CHAR')) {
      PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
      CHAR aChar;
      aChar.read(rs);
      const CHAR::CharacterInfo& ci = aChar.characterInfo;
      charAssoc.m_cmdlRigs[ci.cmdl] = {ci.cskr, ci.cinf};
      charAssoc.m_cskrToCharacter[ci.cskr] =
          std::make_pair(entry.second.id, fmt::format(fmt("{}_{}.CSKR"), ci.name, ci.cskr));
      for (const CHAR::CharacterInfo::Overlay& overlay : ci.overlays) {
        charAssoc.m_cmdlRigs[overlay.cmdl] = {overlay.cskr, ci.cinf};
        charAssoc.m_cskrToCharacter[overlay.cskr] =
            std::make_pair(entry.second.id, fmt::format(fmt("{}.{}_{}.CSKR"), ci.name, overlay.type, overlay.cskr));
      }
    }
  }
}

static const atVec4f BottomRow = {{0.f, 0.f, 0.f, 1.f}};

void PAKBridge::addMAPATransforms(PAKRouter<PAKBridge>& pakRouter,
                                  std::unordered_map<UniqueID64, zeus::CMatrix4f>& addTo,
                                  std::unordered_map<UniqueID64, hecl::ProjectPath>& pathOverrides) const {
  for (const auto& entry : m_pak.m_entries) {
    if (entry.second.type == FOURCC('MLVL')) {
      MLVL mlvl;
      {
        PAKEntryReadStream rs = entry.second.beginReadStream(m_node);
        mlvl.read(rs);
      }
      hecl::ProjectPath mlvlDirPath = pakRouter.getWorking(&entry.second).getParentPath();

      if (mlvl.worldNameId.isValid())
        pathOverrides[mlvl.worldNameId] = hecl::ProjectPath(mlvlDirPath,
            fmt::format(fmt(_SYS_STR("!name_{}.yaml")), mlvl.worldNameId));

      for (const MLVL::Area& area : mlvl.areas) {
        hecl::ProjectPath areaDirPath = pakRouter.getWorking(area.areaMREAId).getParentPath();
        if (area.areaNameId.isValid())
          pathOverrides[area.areaNameId] = hecl::ProjectPath(areaDirPath,
              fmt::format(fmt(_SYS_STR("!name_{}.yaml")), area.areaNameId));
      }

      if (mlvl.worldMap.isValid()) {
        const nod::Node* mapNode;
        const PAK::Entry* mapEntry = pakRouter.lookupEntry(mlvl.worldMap, &mapNode);
        if (mapEntry) {
          PAKEntryReadStream rs = mapEntry->beginReadStream(*mapNode);
          u32 magic = rs.readUint32Big();
          if (magic == 0xDEADF00D) {
            rs.readUint32Big();
            u32 count = rs.readUint32Big();
            for (u32 i = 0; i < count && i < mlvl.areas.size(); ++i) {
              MLVL::Area& areaData = mlvl.areas[i];
              UniqueID64 mapaId;
              mapaId.read(rs);
              addTo[mapaId] = zeus::CMatrix4f(areaData.transformMtx[0], areaData.transformMtx[1],
                                              areaData.transformMtx[2], BottomRow)
                                  .transposed();
            }
          }
        }
      }
    }
  }
}

ResExtractor<PAKBridge> PAKBridge::LookupExtractor(const nod::Node& pakNode, const PAK& pak, const PAK::Entry& entry) {
  switch (entry.type.toUint32()) {
  case SBIG('CAUD'):
    return {CAUD::Extract, {_SYS_STR(".yaml")}};
  case SBIG('STRG'):
    return {STRG::Extract, {_SYS_STR(".yaml")}};
  case SBIG('TXTR'):
    return {TXTR::Extract, {_SYS_STR(".png")}};
  case SBIG('SAVW'):
    return {SAVWCommon::ExtractSAVW<SAVW>, {_SYS_STR(".yaml")}};
  case SBIG('HINT'):
    return {HINT::Extract, {_SYS_STR(".yaml")}};
//  case SBIG('CMDL'):
//    return {CMDL::Extract, {_SYS_STR(".blend")}, 1};
//  case SBIG('CHAR'):
//    return {CHAR::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 2};
//  case SBIG('MLVL'):
//    return {MLVL::Extract, {_SYS_STR(".yaml"), _SYS_STR(".blend")}, 3};
//  case SBIG('MREA'):
//    return {MREA::Extract, {_SYS_STR(".blend")}, 4};
//  case SBIG('MAPA'):
//    return {MAPA::Extract, {_SYS_STR(".blend")}, 4};
  case SBIG('FSM2'):
    return {DNAFSM2::ExtractFSM2<UniqueID64>, {_SYS_STR(".yaml")}};
  case SBIG('FONT'):
    return {DNAFont::ExtractFONT<UniqueID64>, {_SYS_STR(".yaml")}};
  case SBIG('DGRP'):
    return {DNADGRP::ExtractDGRP<UniqueID64>, {_SYS_STR(".yaml")}};
  }
  return {};
}

} // namespace DataSpec::DNAMP3
<|endoftext|>


<commit_before>//@author A0094446X
#include "stdafx.h"
#include "CppUnitTest.h"
#include "You-GUI\main_window.h"
#include "You-GUI\system_tray_manager.h"
#include "You-QueryEngine\api.h"
#include "You-GUI\task_panel_manager.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Task = You::Controller::Task;
using TaskList = You::Controller::TaskList;
using Date = boost::gregorian::date;
namespace You {
namespace GUI {
namespace UnitTests {
QApplication *app;
// Simulate running the main() function
// Sets up the logging facility and the Qt event loop

TEST_MODULE_INITIALIZE(ModuleInitialize) {
	int argc = 1;
	char *argv[] = { "You.exe" };
	app = new QApplication(argc, argv);
}

// Cleans up what we set up
TEST_MODULE_CLEANUP(ModuleCleanup) {
	app->quit();
	delete app;
}

TEST_CLASS(MainWindowTests) {
public:
	/// These are generic tests for component visibility/invisibility
	TEST_METHOD(visibilityTest) {
		MainWindow w;
		bool visibilityTest =
			w.isVisible() &&
			w.ui.centralWidget->isVisible() &&
			w.ui.taskTreePanel->isVisible() &&
			w.ui.commandEnterButton->isVisible() &&
			w.commandTextBox->isVisible() &&
			w.ui.statusBar->isVisible() &&
			w.ui.statusIcon->isVisible() &&
			w.ui.statusMessage->isVisible() &&
			!w.ui.mainToolBar->isVisible() &&
			!w.ui.menuBar->isVisible();
		Assert::IsTrue(visibilityTest);
	}

	/// Basic task addition test
	TEST_METHOD(addSingleTask) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 99"));
		w.commandEnterPressed();

		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("test"));
		int column3 = QString::compare(
			item.text(3),
			QString("Overdue (1999-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));

		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1 &&
			(column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	/// Boundary test case for the equivalence partition for the lower
	/// bound of the valid zone for testing if a task is due today
	TEST_METHOD(testDueToday1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due today (deadline ahead)
	TEST_METHOD(testDueToday2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24) + boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due today (deadline before)
	TEST_METHOD(testDueToday3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due
	/// tomorrow (deadline after)
	TEST_METHOD(testDueTomorrow1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24);
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 1));
	}

	/// Boundary test case for the equivalence partition for the upper
	/// bound of the lower invalid zone for testing if a task is overdue
	TEST_METHOD(testPastDue1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= boost::posix_time::minutes(1);
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Generic test case for testing if a task is overdue
	TEST_METHOD(testPastDue2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, on the same time
	TEST_METHOD(testPastDue3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, with deadline 1 minute after
	TEST_METHOD(testPastDue4) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Generic task deletion test
	TEST_METHOD(deleteSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	/// Generic task deletion test
	TEST_METHOD(deleteSingleTaskFind) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->findItems(
			QString("1"), Qt::MatchExactly, 1).size() == 0);
	}

	TEST_METHOD(editSingleTask) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 99"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(
			QString("/edit 0 set description abc"));
		w.commandEnterButtonClicked();
		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("abc"));
		int column3 = QString::compare(
			item.text(3),
			QString("Overdue (1999-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));

		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1 &&
			(column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	TEST_METHOD(toggleTrayIcon) {
		MainWindow w;
		w.clearTasks();

		Assert::IsTrue(true);
	}
};
}  // namespace UnitTests
}  // namespace GUI
}  // namespace You
<commit_msg>I stayed awake for this single whitespace lint error.<commit_after>//@author A0094446X
#include "stdafx.h"
#include "CppUnitTest.h"
#include "You-GUI\main_window.h"
#include "You-GUI\system_tray_manager.h"
#include "You-QueryEngine\api.h"
#include "You-GUI\task_panel_manager.h"

using Assert = Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Task = You::Controller::Task;
using TaskList = You::Controller::TaskList;
using Date = boost::gregorian::date;
namespace You {
namespace GUI {
namespace UnitTests {
QApplication *app;
// Simulate running the main() function
// Sets up the logging facility and the Qt event loop

TEST_MODULE_INITIALIZE(ModuleInitialize) {
	int argc = 1;
	char *argv[] = { "You.exe" };
	app = new QApplication(argc, argv);
}

// Cleans up what we set up
TEST_MODULE_CLEANUP(ModuleCleanup) {
	app->quit();
	delete app;
}

TEST_CLASS(MainWindowTests) {
public:
	/// These are generic tests for component visibility/invisibility
	TEST_METHOD(visibilityTest) {
		MainWindow w;
		bool visibilityTest =
			w.isVisible() &&
			w.ui.centralWidget->isVisible() &&
			w.ui.taskTreePanel->isVisible() &&
			w.ui.commandEnterButton->isVisible() &&
			w.commandTextBox->isVisible() &&
			w.ui.statusBar->isVisible() &&
			w.ui.statusIcon->isVisible() &&
			w.ui.statusMessage->isVisible() &&
			!w.ui.mainToolBar->isVisible() &&
			!w.ui.menuBar->isVisible();
		Assert::IsTrue(visibilityTest);
	}

	/// Basic task addition test
	TEST_METHOD(addSingleTask) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 99"));
		w.commandEnterPressed();

		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("test"));
		int column3 = QString::compare(
			item.text(3),
			QString("Overdue (1999-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));

		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1 &&
			(column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	/// Boundary test case for the equivalence partition for the lower
	/// bound of the valid zone for testing if a task is due today
	TEST_METHOD(testDueToday1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due today (deadline ahead)
	TEST_METHOD(testDueToday2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24) + boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due today (deadline before)
	TEST_METHOD(testDueToday3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsFalse(MainWindow::TaskPanelManager::isDueAfter(dl, 0));
	}

	/// Generic test case for testing if a task is due
	/// tomorrow (deadline after)
	TEST_METHOD(testDueTomorrow1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::hours(24);
		Assert::IsTrue(MainWindow::TaskPanelManager::isDueAfter(dl, 1));
	}

	/// Boundary test case for the equivalence partition for the upper
	/// bound of the lower invalid zone for testing if a task is overdue
	TEST_METHOD(testPastDue1) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= boost::posix_time::minutes(1);
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Generic test case for testing if a task is overdue
	TEST_METHOD(testPastDue2) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl -= (boost::posix_time::hours(24) + boost::posix_time::minutes(1));
		Assert::IsTrue(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, on the same time
	TEST_METHOD(testPastDue3) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Test if is past due, with deadline 1 minute after
	TEST_METHOD(testPastDue4) {
		MainWindow w;
		Task::Time dl = boost::posix_time::second_clock::local_time();
		dl += boost::posix_time::minutes(1);
		Assert::IsFalse(MainWindow::TaskPanelManager::isPastDue(dl));
	}

	/// Generic task deletion test
	TEST_METHOD(deleteSingleTaskCount) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1);
	}

	/// Generic task deletion test
	TEST_METHOD(deleteSingleTaskFind) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/add test2 by Nov 20"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(QString("/delete 1"));
		w.commandEnterPressed();
		Assert::IsTrue(w.ui.taskTreePanel->findItems(
			QString("1"), Qt::MatchExactly, 1).size() == 0);
	}

	TEST_METHOD(editSingleTask) {
		MainWindow w;
		w.clearTasks();
		w.commandTextBox->setPlainText(QString("/add test by Nov 99"));
		w.commandEnterPressed();
		w.commandTextBox->setPlainText(
			QString("/edit 0 set description abc"));
		w.commandEnterButtonClicked();
		QTreeWidgetItem item = *w.ui.taskTreePanel->topLevelItem(0);
		int column1 = QString::compare(item.text(1), QString("0"));
		int column2 = QString::compare(item.text(2), QString("abc"));
		int column3 = QString::compare(
			item.text(3),
			QString("Overdue (1999-Nov-01 00:00:00)"));
		int column4 = QString::compare(item.text(4), QString("Normal"));

		Assert::IsTrue(w.ui.taskTreePanel->topLevelItemCount() == 1 &&
			(column1 == 0) && (column2 == 0) &&
			(column3 == 0) && (column4 == 0));
	}

	TEST_METHOD(toggleTrayIcon) {
		MainWindow w;
		w.clearTasks();
		Assert::IsTrue(true);
	}
};
}  // namespace UnitTests
}  // namespace GUI
}  // namespace You
<|endoftext|>


<commit_before>#include "libtorrent/lazy_entry.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>

#include "test.hpp"
#include "libtorrent/time.hpp"

using namespace libtorrent;

int test_main()
{
	using namespace libtorrent;

	ptime start(time_now());

	for (int i = 0; i < 1000000; ++i)
	{
		char b[] = "d1:ai12453e1:b3:aaa1:c3:bbbe";
		lazy_entry e;
		int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
	}
	ptime stop(time_now());

	std::cout << "done in " << total_milliseconds(stop - start) / 1000. << " seconds per million message" << std::endl;
	return 0;
}

<commit_msg>made test_bdecode_performance run in a more reasonable amount of time<commit_after>#include "libtorrent/lazy_entry.hpp"
#include <boost/lexical_cast.hpp>
#include <iostream>

#include "test.hpp"
#include "libtorrent/time.hpp"

using namespace libtorrent;

int test_main()
{
	using namespace libtorrent;

	ptime start(time_now());

	for (int i = 0; i < 100000; ++i)
	{
		char b[] = "d1:ai12453e1:b3:aaa1:c3:bbbe";
		lazy_entry e;
		int ret = lazy_bdecode(b, b + sizeof(b)-1, e);
	}
	ptime stop(time_now());

	std::cout << "done in " << total_milliseconds(stop - start) / 100. << " seconds per million message" << std::endl;
	return 0;
}

<|endoftext|>


<commit_before>#include <climits>
#include <array>

#include <elevator/test.h>
#include <elevator/driver.h>
#include <elevator/channels.h>

namespace elevator {

static const int N_FLOORS = 4;
static const int N_BUTTONS = 3;

static const std::array< std::array< int, N_BUTTONS >, N_FLOORS > lampChannelMatrix{ {
    { { LIGHT_UP1, LIGHT_DOWN1, LIGHT_COMMAND1 } },
    { { LIGHT_UP2, LIGHT_DOWN2, LIGHT_COMMAND2 } },
    { { LIGHT_UP3, LIGHT_DOWN3, LIGHT_COMMAND3 } },
    { { LIGHT_UP4, LIGHT_DOWN4, LIGHT_COMMAND4 } },
} };

static const std::array< std::array< int, N_BUTTONS >, N_FLOORS > buttonChannelMatrix{ {
    { { FLOOR_UP1, FLOOR_DOWN1, FLOOR_COMMAND1 } },
    { { FLOOR_UP2, FLOOR_DOWN2, FLOOR_COMMAND2 } },
    { { FLOOR_UP3, FLOOR_DOWN3, FLOOR_COMMAND3 } },
    { { FLOOR_UP4, FLOOR_DOWN4, FLOOR_COMMAND4 } },
} };

int lamp( Button btn ) {
    assert_leq( btn.floor(), int( lampChannelMatrix.size() ), "out-of-bounds" );
    assert_leq( 1, btn.floor(), "out-of-bounds" );

    return lampChannelMatrix[ btn.floor() - 1 ][ int( btn.type() ) ];
}

int button( Button btn ) {
    assert_leq( btn.floor(), int( buttonChannelMatrix.size() ), "out-of-bounds" );
    assert_leq( 1, btn.floor(), "out-of-bounds" );

    return buttonChannelMatrix[ btn.floor() - 1 ][ int( btn.type() ) ];
}

Driver::Driver() : _minFloor( 1 ), _maxFloor( 4 ),
    // we don't know what to set yet, just plug in some sensible values
    _lastDirection( Direction::Down ), _lastFloor( 1 ), _moving( false )
{
    stopElevator(); // for safety reasons
    int sensor = getFloor();
    if ( sensor != -1 )
        _lastFloor = sensor;
}

/** be nicer to elevator
 * in case exception is thrown there is chance elevator is running, if
 * Driver goes out of scope we want elevator to stop for safety reasons
 */
Driver::~Driver() { stopElevator(); }

void Driver::init() {
    for ( int i = _minFloor; i <= _maxFloor; ++i ) {
        if ( i != _maxFloor )
            setButtonLamp( Button{ ButtonType::CallUp, i }, false );
        if ( i != _minFloor )
            setButtonLamp( Button{ ButtonType::CallDown, i }, false );
        setButtonLamp( Button{ ButtonType::TargetFloor, i }, false );
    }

    setStopLamp( false );
    setDoorOpenLamp( false );

    goToBottom();
}

void Driver::shutdown() {
    init(); // for now
}

void Driver::setButtonLamp( Button btn, bool state ) {
    _lio.io_set_bit( lamp( btn ), state );
}

void Driver::setStopLamp( bool state ) {
    _lio.io_set_bit( LIGHT_STOP, state );
}

void Driver::setDoorOpenLamp( bool state ) {
    _lio.io_set_bit( DOOR_OPEN, state );

}

void Driver::setFloorIndicator( int floor ) {
    assert_leq( _minFloor, floor, "floor out of bounds" );
    assert_leq( floor, _maxFloor, "floor out of bounds" );
    --floor; // floor numers are from 0 in backend but from 1 in driver and labels

    _lio.io_set_bit(FLOOR_IND1, (floor & 0x02) == 0x02 );
    _lio.io_set_bit(FLOOR_IND2, (floor & 0x01) == 0x01 );
}

bool Driver::getButtonLamp( Button button ) {
    return _lio.io_read_bit( lamp( button ) );
}

bool Driver::getStopLamp() {
    return _lio.io_read_bit( LIGHT_STOP );
}

bool Driver::getDoorOpenLamp() {
    return _lio.io_read_bit( DOOR_OPEN );
}

int Driver::getFloorIndicator() {
    return ((_lio.io_read_bit( FLOOR_IND1 ) << 1) | (_lio.io_read_bit( FLOOR_IND2 ))) + 1;
}

bool Driver::getButtonSignal( Button btn ) {
    return _lio.io_read_bit( button( btn ) );
}

void Driver::setMotorSpeed( Direction direction, int speed ) {
    assert_lt( 0, speed, "Speed must be positive" );
    _lastDirection = direction;
    _lio.io_set_bit( MOTORDIR, direction == Direction::Down );
    _lio.io_write_analog( MOTOR, 2048 + 4 * speed );
};

void Driver::stopElevator() {
    _lio.io_set_bit( MOTORDIR, _lastDirection == Direction::Up ); // reverse direction
    _lio.io_write_analog( MOTOR, 0 ); // actually stop
    _moving = false;
};

int Driver::getFloor() {
    if ( _lio.io_read_bit( SENSOR1 ) )
        return 1;
    else if ( _lio.io_read_bit( SENSOR2 ) )
        return 2;
    else if ( _lio.io_read_bit( SENSOR3 ) )
        return 3;
    else if ( _lio.io_read_bit( SENSOR4 ) )
        return 4;
    else
        return INT_MIN;

};
bool Driver::getStop() { assert_unimplemented(); };
bool Driver::getObstruction() { assert_unimplemented(); };

void Driver::goToFloor( int floor ) {
    assert_leq( _minFloor, floor, "floor out of bounds" );
    assert_leq( floor, _maxFloor, "floor out of bounds" );
    assert( !_moving, "inconsistent state" );
    if ( floor == _lastFloor )
        return;
    if ( floor < _lastFloor )
        goDownToFloor( floor );
    else
        goUpToFloor( floor );
}

void Driver::goUpToFloor( int floor ) {
    _goTo( Direction::Up, floor );
}

void Driver::goDownToFloor( int floor ) {
    _goTo( Direction::Down, floor );
}

void Driver::goToBottom() { goDownToFloor( _minFloor ); }
void Driver::goToTop() { goUpToFloor( _maxFloor ); }

void Driver::_goTo( Direction dir, int targetFloor ) {
    setMotorSpeed( dir, 300 );
    int on;
    while ( true ) {
        on = getFloor();
        movingOnFloor( on );
        if ( on == targetFloor )
            break;
        if ( dir == Direction::Up && on == _maxFloor )
            break;
        if ( dir == Direction::Down && on == _minFloor )
            break;
    }
    stopElevator();
    setFloorIndicator( targetFloor );
}

void Driver::movingOnFloor( int floorSensor ) {
    if ( floorSensor != INT_MIN ) {
        _lastFloor = floorSensor;
        setFloorIndicator( floorSensor );
    }
    _moving = true;
}

bool Driver::alive() {
    if ( getStopLamp() )
        return true;
    setStopLamp( true );
    bool val = getStopLamp();
    setStopLamp( false );
    return val;
}

}
<commit_msg>driver: Implement missing functions.<commit_after>#include <climits>
#include <array>

#include <elevator/test.h>
#include <elevator/driver.h>
#include <elevator/channels.h>

namespace elevator {

static const int N_FLOORS = 4;
static const int N_BUTTONS = 3;

static const std::array< std::array< int, N_BUTTONS >, N_FLOORS > lampChannelMatrix{ {
    { { LIGHT_UP1, LIGHT_DOWN1, LIGHT_COMMAND1 } },
    { { LIGHT_UP2, LIGHT_DOWN2, LIGHT_COMMAND2 } },
    { { LIGHT_UP3, LIGHT_DOWN3, LIGHT_COMMAND3 } },
    { { LIGHT_UP4, LIGHT_DOWN4, LIGHT_COMMAND4 } },
} };

static const std::array< std::array< int, N_BUTTONS >, N_FLOORS > buttonChannelMatrix{ {
    { { FLOOR_UP1, FLOOR_DOWN1, FLOOR_COMMAND1 } },
    { { FLOOR_UP2, FLOOR_DOWN2, FLOOR_COMMAND2 } },
    { { FLOOR_UP3, FLOOR_DOWN3, FLOOR_COMMAND3 } },
    { { FLOOR_UP4, FLOOR_DOWN4, FLOOR_COMMAND4 } },
} };

int lamp( Button btn ) {
    assert_leq( btn.floor(), int( lampChannelMatrix.size() ), "out-of-bounds" );
    assert_leq( 1, btn.floor(), "out-of-bounds" );

    return lampChannelMatrix[ btn.floor() - 1 ][ int( btn.type() ) ];
}

int button( Button btn ) {
    assert_leq( btn.floor(), int( buttonChannelMatrix.size() ), "out-of-bounds" );
    assert_leq( 1, btn.floor(), "out-of-bounds" );

    return buttonChannelMatrix[ btn.floor() - 1 ][ int( btn.type() ) ];
}

Driver::Driver() : _minFloor( 1 ), _maxFloor( 4 ),
    // we don't know what to set yet, just plug in some sensible values
    _lastDirection( Direction::Down ), _lastFloor( 1 ), _moving( false )
{
    stopElevator(); // for safety reasons
    int sensor = getFloor();
    if ( sensor != -1 )
        _lastFloor = sensor;
}

/** be nicer to elevator
 * in case exception is thrown there is chance elevator is running, if
 * Driver goes out of scope we want elevator to stop for safety reasons
 */
Driver::~Driver() { stopElevator(); }

void Driver::init() {
    for ( int i = _minFloor; i <= _maxFloor; ++i ) {
        if ( i != _maxFloor )
            setButtonLamp( Button{ ButtonType::CallUp, i }, false );
        if ( i != _minFloor )
            setButtonLamp( Button{ ButtonType::CallDown, i }, false );
        setButtonLamp( Button{ ButtonType::TargetFloor, i }, false );
    }

    setStopLamp( false );
    setDoorOpenLamp( false );

    goToBottom();
}

void Driver::shutdown() {
    init(); // for now
}

void Driver::setButtonLamp( Button btn, bool state ) {
    _lio.io_set_bit( lamp( btn ), state );
}

void Driver::setStopLamp( bool state ) {
    _lio.io_set_bit( LIGHT_STOP, state );
}

void Driver::setDoorOpenLamp( bool state ) {
    _lio.io_set_bit( DOOR_OPEN, state );

}

void Driver::setFloorIndicator( int floor ) {
    assert_leq( _minFloor, floor, "floor out of bounds" );
    assert_leq( floor, _maxFloor, "floor out of bounds" );
    --floor; // floor numers are from 0 in backend but from 1 in driver and labels

    _lio.io_set_bit(FLOOR_IND1, (floor & 0x02) == 0x02 );
    _lio.io_set_bit(FLOOR_IND2, (floor & 0x01) == 0x01 );
}

bool Driver::getButtonLamp( Button button ) {
    return _lio.io_read_bit( lamp( button ) );
}

bool Driver::getStopLamp() {
    return _lio.io_read_bit( LIGHT_STOP );
}

bool Driver::getDoorOpenLamp() {
    return _lio.io_read_bit( DOOR_OPEN );
}

int Driver::getFloorIndicator() {
    return ((_lio.io_read_bit( FLOOR_IND1 ) << 1) | (_lio.io_read_bit( FLOOR_IND2 ))) + 1;
}

bool Driver::getButtonSignal( Button btn ) {
    return _lio.io_read_bit( button( btn ) );
}

void Driver::setMotorSpeed( Direction direction, int speed ) {
    assert_lt( 0, speed, "Speed must be positive" );
    _lastDirection = direction;
    _lio.io_set_bit( MOTORDIR, direction == Direction::Down );
    _lio.io_write_analog( MOTOR, 2048 + 4 * speed );
};

void Driver::stopElevator() {
    _lio.io_set_bit( MOTORDIR, _lastDirection == Direction::Up ); // reverse direction
    _lio.io_write_analog( MOTOR, 0 ); // actually stop
    _moving = false;
};

int Driver::getFloor() {
    if ( _lio.io_read_bit( SENSOR1 ) )
        return 1;
    else if ( _lio.io_read_bit( SENSOR2 ) )
        return 2;
    else if ( _lio.io_read_bit( SENSOR3 ) )
        return 3;
    else if ( _lio.io_read_bit( SENSOR4 ) )
        return 4;
    else
        return INT_MIN;

};
bool Driver::getStop() { return _lio.io_read_bit( STOP );};
bool Driver::getObstruction() { return _lio.io_read_bit( OBSTRUCTION ); };

void Driver::goToFloor( int floor ) {
    assert_leq( _minFloor, floor, "floor out of bounds" );
    assert_leq( floor, _maxFloor, "floor out of bounds" );
    assert( !_moving, "inconsistent state" );
    if ( floor == _lastFloor )
        return;
    if ( floor < _lastFloor )
        goDownToFloor( floor );
    else
        goUpToFloor( floor );
}

void Driver::goUpToFloor( int floor ) {
    _goTo( Direction::Up, floor );
}

void Driver::goDownToFloor( int floor ) {
    _goTo( Direction::Down, floor );
}

void Driver::goToBottom() { goDownToFloor( _minFloor ); }
void Driver::goToTop() { goUpToFloor( _maxFloor ); }

void Driver::_goTo( Direction dir, int targetFloor ) {
    setMotorSpeed( dir, 300 );
    int on;
    while ( true ) {
        on = getFloor();
        movingOnFloor( on );
        if ( on == targetFloor )
            break;
        if ( dir == Direction::Up && on == _maxFloor )
            break;
        if ( dir == Direction::Down && on == _minFloor )
            break;
    }
    stopElevator();
    setFloorIndicator( targetFloor );
}

void Driver::movingOnFloor( int floorSensor ) {
    if ( floorSensor != INT_MIN ) {
        _lastFloor = floorSensor;
        setFloorIndicator( floorSensor );
    }
    _moving = true;
}

bool Driver::alive() {
    if ( getStopLamp() )
        return true;
    setStopLamp( true );
    bool val = getStopLamp();
    setStopLamp( false );
    return val;
}

}
<|endoftext|>