<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <algorithm>

#include <windows.h>
#include <process.h>

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/task.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/installer/util/google_update_settings.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

// The RLZ is a DLL that might not be present in the system. We load it
// as needed but never unload it.
volatile HMODULE rlz_dll = NULL;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;

extern "C" {
typedef bool (*RecordProductEventFn)(RLZTracker::Product product,
                                     RLZTracker::AccessPoint point,
                                     RLZTracker::Event event_id,
                                     void* reserved);

typedef bool (*GetAccessPointRlzFn)(RLZTracker::AccessPoint point,
                                    wchar_t* rlz,
                                    DWORD rlz_size,
                                    void* reserved);

typedef bool (*ClearAllProductEventsFn)(RLZTracker::Product product,
                                        void* reserved);

typedef bool (*SendFinancialPingFn)(RLZTracker::Product product,
                                    RLZTracker::AccessPoint* access_points,
                                    const WCHAR* product_signature,
                                    const WCHAR* product_brand,
                                    const WCHAR* product_id,
                                    const WCHAR* product_lang,
                                    bool exclude_id,
                                    void* reserved);
}  // extern "C".

RecordProductEventFn record_event = NULL;
GetAccessPointRlzFn get_access_point = NULL;
ClearAllProductEventsFn clear_all_events = NULL;
SendFinancialPingFn send_ping = NULL;

template <typename FuncT>
FuncT WireExport(HMODULE module, const char* export_name) {
  if (!module)
    return NULL;
  void* entry_point = ::GetProcAddress(module, export_name);
  return reinterpret_cast<FuncT>(entry_point);
}

HMODULE LoadRLZLibraryInternal(int directory_key) {
  FilePath rlz_path;
  if (!PathService::Get(directory_key, &rlz_path))
    return NULL;
  rlz_path = rlz_path.AppendASCII("rlz.dll");
  return ::LoadLibraryW(rlz_path.value().c_str());
}

bool LoadRLZLibrary(int directory_key) {
  rlz_dll = LoadRLZLibraryInternal(directory_key);
  if (!rlz_dll) {
    // As a last resort we can try the EXE directory.
    if (directory_key != base::DIR_EXE)
      rlz_dll = LoadRLZLibraryInternal(base::DIR_EXE);
  }
  if (rlz_dll) {
    record_event =
        WireExport<RecordProductEventFn>(rlz_dll, "RecordProductEvent");
    get_access_point =
        WireExport<GetAccessPointRlzFn>(rlz_dll, "GetAccessPointRlz");
    clear_all_events =
        WireExport<ClearAllProductEventsFn>(rlz_dll, "ClearAllProductEvents");
    send_ping =
        WireExport<SendFinancialPingFn>(rlz_dll, "SendFinancialPing");
    return (record_event && get_access_point && clear_all_events && send_ping);
  }
  return false;
}

bool SendFinancialPing(const wchar_t* brand, const wchar_t* lang,
                       const wchar_t* referral, bool exclude_id) {
  RLZTracker::AccessPoint points[] = {RLZTracker::CHROME_OMNIBOX,
                                      RLZTracker::CHROME_HOME_PAGE,
                                      RLZTracker::NO_ACCESS_POINT};
  if (!send_ping)
    return false;
  return send_ping(RLZTracker::CHROME, points, L"chrome", brand, referral, lang,
                   exclude_id, NULL);
}

// This class leverages the AutocompleteEditModel notification to know when
// the user first interacted with the omnibox and set a global accordingly.
class OmniBoxUsageObserver : public NotificationObserver {
 public:
  OmniBoxUsageObserver() {
    registrar_.Add(this, NotificationType::OMNIBOX_OPENED_URL,
                   NotificationService::AllSources());
    omnibox_used_ = false;
    DCHECK(!instance_);
    instance_ = this;
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    // Try to record event now, else set the flag to try later when we
    // attempt the ping.
    if (!RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                        RLZTracker::CHROME_OMNIBOX,
                                        RLZTracker::FIRST_SEARCH))
      omnibox_used_ = true;
    delete this;
  }

  static bool used() {
    return omnibox_used_;
  }

  // Deletes the single instance of OmniBoxUsageObserver.
  static void DeleteInstance() {
    delete instance_;
  }

 private:
  // Dtor is private so the object cannot be created on the stack.
  ~OmniBoxUsageObserver() {
    instance_ = NULL;
  }

  static bool omnibox_used_;

  // There should only be one instance created at a time, and instance_ points
  // to that instance.
  // NOTE: this is only non-null for the amount of time it is needed. Once the
  // instance_ is no longer needed (or Chrome is exiting), this is null.
  static OmniBoxUsageObserver* instance_;

  NotificationRegistrar registrar_;
};

bool OmniBoxUsageObserver::omnibox_used_ = false;
OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;

// This task is run in the file thread, so to not block it for a long time
// we use a throwaway thread to do the blocking url request.
class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet. There is logic inside RLZ dll
  // that throttles it to a maximum of one ping per day.
  static void _cdecl PingNow(void*) {
    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    std::wstring referral;
    GoogleUpdateSettings::GetReferral(&referral);
    if (SendFinancialPing(brand.c_str(), lang.c_str(), referral.c_str(),
                          is_organic(brand))) {
      access_values_state = ACCESS_VALUES_STALE;
      GoogleUpdateSettings::ClearReferral();
    }
  }

  // Organic brands all start with GG, such as GGCM.
  static bool is_organic(const std::wstring& brand) {
    return (brand.size() < 2) ? false : (brand.substr(0,2) == L"GG");
  }

};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(int directory_key, bool first_run)
      : directory_key_(directory_key), first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    // For non-interactive tests we don't do the rest of the initialization
    // because sometimes the very act of loading the dll causes QEMU to crash.
    if (::GetEnvironmentVariableW(env_vars::kHeadless, NULL, 0))
      return;
    // For organic brandcodes do not use rlz at all. Empty brandcode usually
    // means a chromium install. This is ok.
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    if (is_strict_organic(brand))
      return;

    if (!LoadRLZLibrary(directory_key_))
      return;
    // Do the initial event recording if is the first run or if we have an
    // empty rlz which means we haven't got a chance to do it.
    std::wstring omnibox_rlz;
    RLZTracker::GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, &omnibox_rlz);

    if (first_run_ || omnibox_rlz.empty()) {
      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::INSTALL);
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_HOME_PAGE,
                                     RLZTracker::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                       RLZTracker::CHROME_OMNIBOX,
                                       RLZTracker::SET_TO_GOOGLE);
      }
    }
    // Record first user interaction with the omnibox. We call this all the
    // time but the rlz lib should ingore all but the first one.
    if (OmniBoxUsageObserver::used()) {
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::FIRST_SEARCH);
    }
    // Schedule the daily RLZ ping.
    base::Thread* thread = g_browser_process->file_thread();
    if (thread)
      thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    FilePath user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    const TemplateURLRef* urlref = url_template->url();
    if (!urlref)
      return false;
    return urlref->HasGoogleBaseURLs();
  }

  static bool is_strict_organic(const std::wstring& brand) {
    static const wchar_t* kBrands[] = {
        L"CHFO", L"CHFT", L"CHMA", L"CHMB", L"CHME", L"CHMF", L"CHMG", L"CHMH",
        L"CHMI", L"CHMQ", L"CHMV", L"CHNB", L"CHNC", L"CHNG", L"CHNH", L"CHNI",
        L"CHOA", L"CHOB", L"CHOC", L"CHON", L"CHOO", L"CHOP", L"CHOQ", L"CHOR",
        L"CHOS", L"CHOT", L"CHOU", L"CHOX", L"CHOY", L"CHOZ", L"CHPD", L"CHPE",
        L"CHPF", L"CHPG", L"EUBB", L"EUBC", L"GGLA", L"GGLS" };
    const wchar_t** end = &kBrands[arraysize(kBrands)];
    const wchar_t** found = std::find(&kBrands[0], end, brand);
    if (found != end)
      return true;
    if (StartsWith(brand, L"EUB", true) || StartsWith(brand, L"EUC", true))
      return true;
    return false;
  }

  int directory_key_;
  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

}  // namespace

bool RLZTracker::InitRlz(int directory_key) {
  return LoadRLZLibrary(directory_key);
}

bool RLZTracker::InitRlzDelayed(int directory_key, bool first_run, int delay) {
  // Maximum and minimum delay we would allow to be set through master
  // preferences. Somewhat arbitrary, may need to be adjusted in future.
  const int kMaxDelay = 200 * 1000;
  const int kMinDelay = 20 * 1000;

  delay *= 1000;
  delay = (delay < kMinDelay) ? kMinDelay : delay;
  delay = (delay > kMaxDelay) ? kMaxDelay : delay;

  if (!OmniBoxUsageObserver::used())
    new OmniBoxUsageObserver();

  // Schedule the delayed init items.
  MessageLoop::current()->PostDelayedTask(FROM_HERE,
      new DelayedInitTask(directory_key, first_run), delay);
  return true;
}

bool RLZTracker::RecordProductEvent(Product product, AccessPoint point,
                                    Event event) {
  return (record_event) ? record_event(product, point, event, NULL) : false;
}

bool RLZTracker::ClearAllProductEvents(Product product) {
  return (clear_all_events) ? clear_all_events(product, NULL) : false;
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(AccessPoint point, std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (!get_access_point)
    return false;
  if ((CHROME_OMNIBOX == point) &&
      (access_values_state == ACCESS_VALUES_FRESH)) {
    *rlz = cached_ommibox_rlz;
    return true;
  }
  wchar_t str_rlz[kMaxRlzLength];
  if (!get_access_point(point, str_rlz, kMaxRlzLength, NULL))
    return false;
  if (CHROME_OMNIBOX == point) {
    access_values_state = ACCESS_VALUES_FRESH;
    cached_ommibox_rlz.assign(str_rlz);
  }
  *rlz = str_rlz;
  return true;
}

// static
void RLZTracker::CleanupRlz() {
  OmniBoxUsageObserver::DeleteInstance();
}
<commit_msg>Changes RLZ organic wildcards to include GGR*<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This code glues the RLZ library DLL with Chrome. It allows Chrome to work
// with or without the DLL being present. If the DLL is not present the
// functions do nothing and just return false.

#include "chrome/browser/rlz/rlz.h"

#include <algorithm>

#include <windows.h>
#include <process.h>

#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/task.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/env_vars.h"
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "chrome/installer/util/google_update_settings.h"

namespace {

// The maximum length of an access points RLZ in wide chars.
const DWORD kMaxRlzLength = 64;

// The RLZ is a DLL that might not be present in the system. We load it
// as needed but never unload it.
volatile HMODULE rlz_dll = NULL;

enum {
  ACCESS_VALUES_STALE,      // Possibly new values available.
  ACCESS_VALUES_FRESH       // The cached values are current.
};

// Tracks if we have tried and succeeded sending the ping. This helps us
// decide if we need to refresh the some cached strings.
volatile int access_values_state = ACCESS_VALUES_STALE;

extern "C" {
typedef bool (*RecordProductEventFn)(RLZTracker::Product product,
                                     RLZTracker::AccessPoint point,
                                     RLZTracker::Event event_id,
                                     void* reserved);

typedef bool (*GetAccessPointRlzFn)(RLZTracker::AccessPoint point,
                                    wchar_t* rlz,
                                    DWORD rlz_size,
                                    void* reserved);

typedef bool (*ClearAllProductEventsFn)(RLZTracker::Product product,
                                        void* reserved);

typedef bool (*SendFinancialPingFn)(RLZTracker::Product product,
                                    RLZTracker::AccessPoint* access_points,
                                    const WCHAR* product_signature,
                                    const WCHAR* product_brand,
                                    const WCHAR* product_id,
                                    const WCHAR* product_lang,
                                    bool exclude_id,
                                    void* reserved);
}  // extern "C".

RecordProductEventFn record_event = NULL;
GetAccessPointRlzFn get_access_point = NULL;
ClearAllProductEventsFn clear_all_events = NULL;
SendFinancialPingFn send_ping = NULL;

template <typename FuncT>
FuncT WireExport(HMODULE module, const char* export_name) {
  if (!module)
    return NULL;
  void* entry_point = ::GetProcAddress(module, export_name);
  return reinterpret_cast<FuncT>(entry_point);
}

HMODULE LoadRLZLibraryInternal(int directory_key) {
  FilePath rlz_path;
  if (!PathService::Get(directory_key, &rlz_path))
    return NULL;
  rlz_path = rlz_path.AppendASCII("rlz.dll");
  return ::LoadLibraryW(rlz_path.value().c_str());
}

bool LoadRLZLibrary(int directory_key) {
  rlz_dll = LoadRLZLibraryInternal(directory_key);
  if (!rlz_dll) {
    // As a last resort we can try the EXE directory.
    if (directory_key != base::DIR_EXE)
      rlz_dll = LoadRLZLibraryInternal(base::DIR_EXE);
  }
  if (rlz_dll) {
    record_event =
        WireExport<RecordProductEventFn>(rlz_dll, "RecordProductEvent");
    get_access_point =
        WireExport<GetAccessPointRlzFn>(rlz_dll, "GetAccessPointRlz");
    clear_all_events =
        WireExport<ClearAllProductEventsFn>(rlz_dll, "ClearAllProductEvents");
    send_ping =
        WireExport<SendFinancialPingFn>(rlz_dll, "SendFinancialPing");
    return (record_event && get_access_point && clear_all_events && send_ping);
  }
  return false;
}

bool SendFinancialPing(const wchar_t* brand, const wchar_t* lang,
                       const wchar_t* referral, bool exclude_id) {
  RLZTracker::AccessPoint points[] = {RLZTracker::CHROME_OMNIBOX,
                                      RLZTracker::CHROME_HOME_PAGE,
                                      RLZTracker::NO_ACCESS_POINT};
  if (!send_ping)
    return false;
  return send_ping(RLZTracker::CHROME, points, L"chrome", brand, referral, lang,
                   exclude_id, NULL);
}

// This class leverages the AutocompleteEditModel notification to know when
// the user first interacted with the omnibox and set a global accordingly.
class OmniBoxUsageObserver : public NotificationObserver {
 public:
  OmniBoxUsageObserver() {
    registrar_.Add(this, NotificationType::OMNIBOX_OPENED_URL,
                   NotificationService::AllSources());
    omnibox_used_ = false;
    DCHECK(!instance_);
    instance_ = this;
  }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    // Try to record event now, else set the flag to try later when we
    // attempt the ping.
    if (!RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                        RLZTracker::CHROME_OMNIBOX,
                                        RLZTracker::FIRST_SEARCH))
      omnibox_used_ = true;
    delete this;
  }

  static bool used() {
    return omnibox_used_;
  }

  // Deletes the single instance of OmniBoxUsageObserver.
  static void DeleteInstance() {
    delete instance_;
  }

 private:
  // Dtor is private so the object cannot be created on the stack.
  ~OmniBoxUsageObserver() {
    instance_ = NULL;
  }

  static bool omnibox_used_;

  // There should only be one instance created at a time, and instance_ points
  // to that instance.
  // NOTE: this is only non-null for the amount of time it is needed. Once the
  // instance_ is no longer needed (or Chrome is exiting), this is null.
  static OmniBoxUsageObserver* instance_;

  NotificationRegistrar registrar_;
};

bool OmniBoxUsageObserver::omnibox_used_ = false;
OmniBoxUsageObserver* OmniBoxUsageObserver::instance_ = NULL;

// This task is run in the file thread, so to not block it for a long time
// we use a throwaway thread to do the blocking url request.
class DailyPingTask : public Task {
 public:
  virtual ~DailyPingTask() {
  }
  virtual void Run() {
    // We use a transient thread because we have no guarantees about
    // how long the RLZ lib can block us.
    _beginthread(PingNow, 0, NULL);
  }

 private:
  // Causes a ping to the server using WinInet. There is logic inside RLZ dll
  // that throttles it to a maximum of one ping per day.
  static void _cdecl PingNow(void*) {
    std::wstring lang;
    GoogleUpdateSettings::GetLanguage(&lang);
    if (lang.empty())
      lang = L"en";
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    std::wstring referral;
    GoogleUpdateSettings::GetReferral(&referral);
    if (SendFinancialPing(brand.c_str(), lang.c_str(), referral.c_str(),
                          is_organic(brand))) {
      access_values_state = ACCESS_VALUES_STALE;
      GoogleUpdateSettings::ClearReferral();
    }
  }

  // Organic brands all start with GG, such as GGCM.
  static bool is_organic(const std::wstring& brand) {
    return (brand.size() < 2) ? false : (brand.substr(0,2) == L"GG");
  }

};

// Performs late RLZ initialization and RLZ event recording for chrome.
// This task needs to run on the UI thread.
class DelayedInitTask : public Task {
 public:
  explicit DelayedInitTask(int directory_key, bool first_run)
      : directory_key_(directory_key), first_run_(first_run) {
  }
  virtual ~DelayedInitTask() {
  }
  virtual void Run() {
    // For non-interactive tests we don't do the rest of the initialization
    // because sometimes the very act of loading the dll causes QEMU to crash.
    if (::GetEnvironmentVariableW(env_vars::kHeadless, NULL, 0))
      return;
    // For organic brandcodes do not use rlz at all. Empty brandcode usually
    // means a chromium install. This is ok.
    std::wstring brand;
    GoogleUpdateSettings::GetBrand(&brand);
    if (is_strict_organic(brand))
      return;

    if (!LoadRLZLibrary(directory_key_))
      return;
    // Do the initial event recording if is the first run or if we have an
    // empty rlz which means we haven't got a chance to do it.
    std::wstring omnibox_rlz;
    RLZTracker::GetAccessPointRlz(RLZTracker::CHROME_OMNIBOX, &omnibox_rlz);

    if (first_run_ || omnibox_rlz.empty()) {
      // Record the installation of chrome.
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::INSTALL);
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_HOME_PAGE,
                                     RLZTracker::INSTALL);
      // Record if google is the initial search provider.
      if (IsGoogleDefaultSearch()) {
        RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                       RLZTracker::CHROME_OMNIBOX,
                                       RLZTracker::SET_TO_GOOGLE);
      }
    }
    // Record first user interaction with the omnibox. We call this all the
    // time but the rlz lib should ingore all but the first one.
    if (OmniBoxUsageObserver::used()) {
      RLZTracker::RecordProductEvent(RLZTracker::CHROME,
                                     RLZTracker::CHROME_OMNIBOX,
                                     RLZTracker::FIRST_SEARCH);
    }
    // Schedule the daily RLZ ping.
    base::Thread* thread = g_browser_process->file_thread();
    if (thread)
      thread->message_loop()->PostTask(FROM_HERE, new DailyPingTask());
  }

 private:
  bool IsGoogleDefaultSearch() {
    if (!g_browser_process)
      return false;
    FilePath user_data_dir;
    if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
      return false;
    ProfileManager* profile_manager = g_browser_process->profile_manager();
    Profile* profile = profile_manager->GetDefaultProfile(user_data_dir);
    if (!profile)
      return false;
    const TemplateURL* url_template =
        profile->GetTemplateURLModel()->GetDefaultSearchProvider();
    if (!url_template)
      return false;
    const TemplateURLRef* urlref = url_template->url();
    if (!urlref)
      return false;
    return urlref->HasGoogleBaseURLs();
  }

  static bool is_strict_organic(const std::wstring& brand) {
    static const wchar_t* kBrands[] = {
        L"CHFO", L"CHFT", L"CHMA", L"CHMB", L"CHME", L"CHMF", L"CHMG", L"CHMH",
        L"CHMI", L"CHMQ", L"CHMV", L"CHNB", L"CHNC", L"CHNG", L"CHNH", L"CHNI",
        L"CHOA", L"CHOB", L"CHOC", L"CHON", L"CHOO", L"CHOP", L"CHOQ", L"CHOR",
        L"CHOS", L"CHOT", L"CHOU", L"CHOX", L"CHOY", L"CHOZ", L"CHPD", L"CHPE",
        L"CHPF", L"CHPG", L"EUBB", L"EUBC", L"GGLA", L"GGLS" };
    const wchar_t** end = &kBrands[arraysize(kBrands)];
    const wchar_t** found = std::find(&kBrands[0], end, brand);
    if (found != end)
      return true;
    if (StartsWith(brand, L"EUB", true) || StartsWith(brand, L"EUC", true) ||
        StartsWith(brand, L"GGR", true))
      return true;
    return false;
  }

  int directory_key_;
  bool first_run_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(DelayedInitTask);
};

}  // namespace

bool RLZTracker::InitRlz(int directory_key) {
  return LoadRLZLibrary(directory_key);
}

bool RLZTracker::InitRlzDelayed(int directory_key, bool first_run, int delay) {
  // Maximum and minimum delay we would allow to be set through master
  // preferences. Somewhat arbitrary, may need to be adjusted in future.
  const int kMaxDelay = 200 * 1000;
  const int kMinDelay = 20 * 1000;

  delay *= 1000;
  delay = (delay < kMinDelay) ? kMinDelay : delay;
  delay = (delay > kMaxDelay) ? kMaxDelay : delay;

  if (!OmniBoxUsageObserver::used())
    new OmniBoxUsageObserver();

  // Schedule the delayed init items.
  MessageLoop::current()->PostDelayedTask(FROM_HERE,
      new DelayedInitTask(directory_key, first_run), delay);
  return true;
}

bool RLZTracker::RecordProductEvent(Product product, AccessPoint point,
                                    Event event) {
  return (record_event) ? record_event(product, point, event, NULL) : false;
}

bool RLZTracker::ClearAllProductEvents(Product product) {
  return (clear_all_events) ? clear_all_events(product, NULL) : false;
}

// We implement caching of the answer of get_access_point() if the request
// is for CHROME_OMNIBOX. If we had a successful ping, then we update the
// cached value.

bool RLZTracker::GetAccessPointRlz(AccessPoint point, std::wstring* rlz) {
  static std::wstring cached_ommibox_rlz;
  if (!get_access_point)
    return false;
  if ((CHROME_OMNIBOX == point) &&
      (access_values_state == ACCESS_VALUES_FRESH)) {
    *rlz = cached_ommibox_rlz;
    return true;
  }
  wchar_t str_rlz[kMaxRlzLength];
  if (!get_access_point(point, str_rlz, kMaxRlzLength, NULL))
    return false;
  if (CHROME_OMNIBOX == point) {
    access_values_state = ACCESS_VALUES_FRESH;
    cached_ommibox_rlz.assign(str_rlz);
  }
  *rlz = str_rlz;
  return true;
}

// static
void RLZTracker::CleanupRlz() {
  OmniBoxUsageObserver::DeleteInstance();
}
<|endoftext|>


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

// This file defines utility functions for X11 (Linux only). This code has been
// ported from XCB since we can't use XCB on Ubuntu while its 32-bit support
// remains woefully incomplete.

#include "chrome/common/x11_util.h"
#include "chrome/common/x11_util_internal.h"

#include <string.h>

#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>

#include <sys/ipc.h>
#include <sys/shm.h>

#include "base/logging.h"
#include "base/gfx/size.h"

namespace x11_util {

Display* GetXDisplay() {
  static Display* display = NULL;

  if (!display)
    display = gdk_x11_get_default_xdisplay();

  return display;
}

static bool DoQuerySharedMemorySupport(Display* dpy) {
  int dummy;
  Bool pixmaps_supported;
  // Query the server's support for shared memory
  if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported))
    return false;
  // If the server doesn't support shared memory, give up. (Note that if
  // |shared_pixmaps| is true, it just means that the server /supports/ shared
  // memory, not that it will work on this connection.)
  if (!pixmaps_supported)
    return false;

  // Next we probe to see if shared memory will really work
  int shmkey = shmget(IPC_PRIVATE, 1, 0666);
  if (shmkey == -1)
    return false;
  void* address = shmat(shmkey, NULL, 0);
  // Mark the shared memory region for deletion
  shmctl(shmkey, IPC_RMID, NULL);

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmid = shmkey;

  gdk_error_trap_push();
  bool result = XShmAttach(dpy, &shminfo);
  XSync(dpy, False);
  if (gdk_error_trap_pop())
    result = false;
  shmdt(address);
  if (!result)
    return false;

  XShmDetach(dpy, &shminfo);
  return true;
}

bool QuerySharedMemorySupport(Display* dpy) {
  static bool shared_memory_support = false;
  static bool shared_memory_support_cached = false;

  if (shared_memory_support_cached)
    return shared_memory_support;

  shared_memory_support = DoQuerySharedMemorySupport(dpy);
  shared_memory_support_cached = true;

  return shared_memory_support;
}

XID GetX11RootWindow() {
  return GDK_WINDOW_XID(gdk_get_default_root_window());
}

XID GetX11WindowFromGtkWidget(GtkWidget* widget) {
  return GDK_WINDOW_XID(widget->window);
}

void* GetVisualFromGtkWidget(GtkWidget* widget) {
  return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget));
}

XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) {
  static XRenderPictFormat* pictformat = NULL;
  if (pictformat)
    return pictformat;

  int dummy;
  if (!XRenderQueryExtension(dpy, &dummy, &dummy))
    CHECK(false) << "XRENDER not supported on display";

  pictformat = XRenderFindVisualFormat(dpy, visual);
  CHECK(pictformat) << "XRENDER does not support default visual";

  return pictformat;
}

XRenderPictFormat* GetRenderARGB32Format(Display* dpy) {
  static XRenderPictFormat* pictformat = NULL;
  if (pictformat)
    return pictformat;

  // First look for a 32-bit format which ignores the alpha value
  XRenderPictFormat templ;
  templ.depth = 32;
  templ.type = PictTypeDirect;
  templ.direct.red = 16;
  templ.direct.green = 8;
  templ.direct.blue = 0;
  templ.direct.redMask = 0xff;
  templ.direct.greenMask = 0xff;
  templ.direct.blueMask = 0xff;
  templ.direct.alphaMask = 0;

  static const unsigned long kMask =
    PictFormatType | PictFormatDepth |
    PictFormatRed | PictFormatRedMask |
    PictFormatGreen | PictFormatGreenMask |
    PictFormatBlue | PictFormatBlueMask |
    PictFormatAlphaMask;

  pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */);
  CHECK(pictformat) << "XRENDER doesn't not support a Skia compatable format";
  // TODO(agl): fallback to a picture format with an alpha channel

  return pictformat;
}

XID AttachSharedMemory(Display* display, int shared_memory_key) {
  DCHECK(QuerySharedMemorySupport(display));

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmid = shared_memory_key;

  // This function is only called if QuerySharedMemorySupport returned true. In
  // which case we've already succeeded in having the X server attach to one of
  // our shared memory segments.
  if (!XShmAttach(display, &shminfo))
    NOTREACHED();

  return shminfo.shmseg;
}

void DetachSharedMemory(Display* display, XID shmseg) {
  DCHECK(QuerySharedMemorySupport(display));

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmseg = shmseg;

  if (!XShmDetach(display, &shminfo))
    NOTREACHED();
}

XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) {
  XID picture = XRenderCreatePicture(
      display, pixmap, GetRenderARGB32Format(display), 0, NULL);

  return picture;
}

void FreePicture(Display* display, XID picture) {
  XRenderFreePicture(display, picture);
}

void FreePixmap(Display* display, XID pixmap) {
  XFreePixmap(display, pixmap);
}

}  // namespace x11_util
<commit_msg>Linux: fix XRENDER support for NX<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This file defines utility functions for X11 (Linux only). This code has been
// ported from XCB since we can't use XCB on Ubuntu while its 32-bit support
// remains woefully incomplete.

#include "chrome/common/x11_util.h"
#include "chrome/common/x11_util_internal.h"

#include <string.h>

#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>

#include <sys/ipc.h>
#include <sys/shm.h>

#include "base/logging.h"
#include "base/gfx/size.h"

namespace x11_util {

Display* GetXDisplay() {
  static Display* display = NULL;

  if (!display)
    display = gdk_x11_get_default_xdisplay();

  return display;
}

static bool DoQuerySharedMemorySupport(Display* dpy) {
  int dummy;
  Bool pixmaps_supported;
  // Query the server's support for shared memory
  if (!XShmQueryVersion(dpy, &dummy, &dummy, &pixmaps_supported))
    return false;
  // If the server doesn't support shared memory, give up. (Note that if
  // |shared_pixmaps| is true, it just means that the server /supports/ shared
  // memory, not that it will work on this connection.)
  if (!pixmaps_supported)
    return false;

  // Next we probe to see if shared memory will really work
  int shmkey = shmget(IPC_PRIVATE, 1, 0666);
  if (shmkey == -1)
    return false;
  void* address = shmat(shmkey, NULL, 0);
  // Mark the shared memory region for deletion
  shmctl(shmkey, IPC_RMID, NULL);

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmid = shmkey;

  gdk_error_trap_push();
  bool result = XShmAttach(dpy, &shminfo);
  XSync(dpy, False);
  if (gdk_error_trap_pop())
    result = false;
  shmdt(address);
  if (!result)
    return false;

  XShmDetach(dpy, &shminfo);
  return true;
}

bool QuerySharedMemorySupport(Display* dpy) {
  static bool shared_memory_support = false;
  static bool shared_memory_support_cached = false;

  if (shared_memory_support_cached)
    return shared_memory_support;

  shared_memory_support = DoQuerySharedMemorySupport(dpy);
  shared_memory_support_cached = true;

  return shared_memory_support;
}

XID GetX11RootWindow() {
  return GDK_WINDOW_XID(gdk_get_default_root_window());
}

XID GetX11WindowFromGtkWidget(GtkWidget* widget) {
  return GDK_WINDOW_XID(widget->window);
}

void* GetVisualFromGtkWidget(GtkWidget* widget) {
  return GDK_VISUAL_XVISUAL(gtk_widget_get_visual(widget));
}

XRenderPictFormat* GetRenderVisualFormat(Display* dpy, Visual* visual) {
  static XRenderPictFormat* pictformat = NULL;
  if (pictformat)
    return pictformat;

  int dummy;
  if (!XRenderQueryExtension(dpy, &dummy, &dummy))
    CHECK(false) << "XRENDER not supported on display";

  pictformat = XRenderFindVisualFormat(dpy, visual);
  CHECK(pictformat) << "XRENDER does not support default visual";

  return pictformat;
}

XRenderPictFormat* GetRenderARGB32Format(Display* dpy) {
  static XRenderPictFormat* pictformat = NULL;
  if (pictformat)
    return pictformat;

  // First look for a 32-bit format which ignores the alpha value
  XRenderPictFormat templ;
  templ.depth = 32;
  templ.type = PictTypeDirect;
  templ.direct.red = 16;
  templ.direct.green = 8;
  templ.direct.blue = 0;
  templ.direct.redMask = 0xff;
  templ.direct.greenMask = 0xff;
  templ.direct.blueMask = 0xff;
  templ.direct.alphaMask = 0;

  static const unsigned long kMask =
    PictFormatType | PictFormatDepth |
    PictFormatRed | PictFormatRedMask |
    PictFormatGreen | PictFormatGreenMask |
    PictFormatBlue | PictFormatBlueMask |
    PictFormatAlphaMask;

  pictformat = XRenderFindFormat(dpy, kMask, &templ, 0 /* first result */);

  if (!pictformat) {
    // Not all X servers support xRGB32 formats. However, the XRENDER spec says
    // that they must support an ARGB32 format, so we can always return that.
    pictformat = XRenderFindStandardFormat(dpy, PictStandardARGB32);
    CHECK(pictformat) << "XRENDER ARGB32 not supported.";
  }

  return pictformat;
}

XID AttachSharedMemory(Display* display, int shared_memory_key) {
  DCHECK(QuerySharedMemorySupport(display));

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmid = shared_memory_key;

  // This function is only called if QuerySharedMemorySupport returned true. In
  // which case we've already succeeded in having the X server attach to one of
  // our shared memory segments.
  if (!XShmAttach(display, &shminfo))
    NOTREACHED();

  return shminfo.shmseg;
}

void DetachSharedMemory(Display* display, XID shmseg) {
  DCHECK(QuerySharedMemorySupport(display));

  XShmSegmentInfo shminfo;
  memset(&shminfo, 0, sizeof(shminfo));
  shminfo.shmseg = shmseg;

  if (!XShmDetach(display, &shminfo))
    NOTREACHED();
}

XID CreatePictureFromSkiaPixmap(Display* display, XID pixmap) {
  XID picture = XRenderCreatePicture(
      display, pixmap, GetRenderARGB32Format(display), 0, NULL);

  return picture;
}

void FreePicture(Display* display, XID picture) {
  XRenderFreePicture(display, picture);
}

void FreePixmap(Display* display, XID pixmap) {
  XFreePixmap(display, pixmap);
}

}  // namespace x11_util
<|endoftext|>


<commit_before><commit_msg>Minor simplification<commit_after><|endoftext|>


<commit_before>#include "plot.h"
#include "curvedata.h"
#include "signaldata.h"
#include <qwt_plot_grid.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_directpainter.h>
#include <qwt_curve_fitter.h>
#include <qwt_painter.h>
#include <qwt_scale_engine.h>
#include <qwt_scale_draw.h>
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_text.h>

#include <qevent.h>

#include <cassert>

class MyPanner : public QObject
{
public:

  QPoint mInitialPos;
  bool mEnabled;
  int mMouseButton;
  int mKeyboardButton;
  Plot* mPlot;

  MyPanner(Plot* plot) : QObject(plot)
  {
    mEnabled = false;
    mMouseButton = Qt::LeftButton;
    mKeyboardButton = Qt::NoButton;
    mPlot = plot;
    mPlot->canvas()->installEventFilter(this);
  }

  bool eventFilter( QObject *object, QEvent *event )
  {
    switch ( event->type() )
    {
      case QEvent::MouseButtonPress:
      {
        widgetMousePressEvent( ( QMouseEvent * )event );
        break;
      }
      case QEvent::MouseMove:
      {
        widgetMouseMoveEvent( ( QMouseEvent * )event );
        break;
      }
      case QEvent::MouseButtonRelease:
      {
        widgetMouseReleaseEvent( ( QMouseEvent * )event );
        break;
      }
    }

    return false;
  }

  void moveCanvas( int dx, int dy )
  {
    if ( dx == 0 && dy == 0 )
        return;

    if (!mPlot->isStopped())
      dx = 0;

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
      const QwtScaleMap map = mPlot->canvasMap( axis );
      const double p1 = map.transform( mPlot->axisScaleDiv( axis )->lowerBound() );
      const double p2 = map.transform( mPlot->axisScaleDiv( axis )->upperBound() );

      double d1, d2;
      if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop )
      {
        d1 = map.invTransform( p1 - dx );
        d2 = map.invTransform( p2 - dx );
      }
      else
      {
        d1 = map.invTransform( p1 - dy );
        d2 = map.invTransform( p2 - dy );
      }
      mPlot->setAxisScale( axis, d1, d2 );
    }

    mPlot->flagAxisSyncRequired();
    mPlot->replot();
  }

  void widgetMousePressEvent( QMouseEvent *mouseEvent )
  {
    if (mouseEvent->button() != mMouseButton)
    {
      return;
    }

    if ((mouseEvent->modifiers() & Qt::KeyboardModifierMask) != (mKeyboardButton & Qt::KeyboardModifierMask))
    {
      return;
    }

    mInitialPos = mouseEvent->pos();
    mEnabled = true;
  }

  void widgetMouseMoveEvent( QMouseEvent *mouseEvent )
  {
    if (!mEnabled)
      return;

    QPoint pos = mouseEvent->pos();
    if (pos != mInitialPos)
    {
      moveCanvas(pos.x() - mInitialPos.x(), pos.y() - mInitialPos.y());
      mInitialPos = mouseEvent->pos();
    }
  }

  void widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
  {
    mEnabled = false;
  }

};

class MyScaleDraw : public QwtScaleDraw
{
  virtual QwtText label(double value) const
  {
    return QString::number(value, 'f', 2);
  }
};

class MyZoomer: public QwtPlotZoomer
{
public:

    Plot* mPlot;

    MyZoomer(Plot *plot) : QwtPlotZoomer(plot->canvas())
    {
      mPlot = plot;
      setTrackerMode(AlwaysOn);
    }

    virtual QwtText trackerTextF(const QPointF &pos) const
    {
      QColor bg(Qt::white);
      bg.setAlpha(200);

      QwtText text = QwtPlotZoomer::trackerTextF(pos);
      text.setBackgroundBrush( QBrush( bg ));
      return text;
    }

protected:

    virtual void rescale()
    {
      mPlot->flagAxisSyncRequired();
      QwtPlotZoomer::rescale();
    }

};

class MyMagnifier: public QwtPlotMagnifier
{
public:
    Plot* mPlot;

    MyMagnifier(Plot* plot) : QwtPlotMagnifier(plot->canvas())
    {
      mPlot = plot;
    }

protected:

    // Normally, a value < 1.0 zooms in, a value > 1.0 zooms out.
    // This function is overloaded to invert the magnification direction.
    virtual void rescale( double factor )
    {
      factor = qAbs( factor );
      factor = (1-factor) + 1;

      mPlot->flagAxisSyncRequired();
      this->QwtPlotMagnifier::rescale(factor);
    }

};

Plot::Plot(QWidget *parent):
  QwtPlot(parent),
  d_origin(0),
  d_grid(0),
  mStopped(true),
  mAxisSyncRequired(false),
  mColorMode(0),
  mTimeWindow(10.0)
{
  setAutoReplot(false);

  // The backing store is important, when working with widget
  // overlays ( f.e rubberbands for zooming ).
  // Here we don't have them and the internal
  // backing store of QWidget is good enough.

  canvas()->setPaintAttribute(QwtPlotCanvas::BackingStore, false);

#if defined(Q_WS_X11)
  // Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent
  // works on X11. This has a nice effect on the performance.

  canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);

  // Disabling the backing store of Qt improves the performance
  // for the direct painter even more, but the canvas becomes
  // a native window of the window system, receiving paint events
  // for resize and expose operations. Those might be expensive
  // when there are many points and the backing store of
  // the canvas is disabled. So in this application
  // we better don't both backing stores.

  if ( canvas()->testPaintAttribute( QwtPlotCanvas::BackingStore ) )
  {
    canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
    canvas()->setAttribute(Qt::WA_NoSystemBackground, true);
  }

#endif

  plotLayout()->setAlignCanvasToScales(true);

  setAxisAutoScale(QwtPlot::xBottom, false);
  setAxisAutoScale(QwtPlot::yLeft, false);

  setAxisTitle(QwtPlot::xBottom, "Time [s]");
  setAxisScale(QwtPlot::xBottom, 0, 10);
  setAxisScale(QwtPlot::yLeft, -4.0, 4.0);

  setAxisScaleDraw(QwtPlot::xBottom, new MyScaleDraw);

  initBackground();

  QwtPlotZoomer* zoomer = new MyZoomer(this);
  zoomer->setMousePattern(QwtEventPattern::QwtEventPattern::MouseSelect1,
      Qt::LeftButton, Qt::ShiftModifier);
  // zoomer->setMousePattern(QwtEventPattern::MouseSelect3,
  //     Qt::RightButton);

  MyPanner *panner = new MyPanner(this);

  // zoom in/out with the wheel
  mMagnifier = new MyMagnifier(this);
  mMagnifier->setMouseButton(Qt::MiddleButton);

  const QColor c(Qt::darkBlue);
  zoomer->setRubberBandPen(c);
  zoomer->setTrackerPen(c);

  this->setMinimumHeight(200);
}

Plot::~Plot()
{

}

void Plot::addSignal(SignalData* signalData, QColor color)
{
  QwtPlotCurve* d_curve = new QwtPlotCurve();
  d_curve->setStyle(QwtPlotCurve::Dots);

  QPen curvePen(color);
  curvePen.setWidth(0);

  d_curve->setPen(curvePen);

#if 1
  d_curve->setRenderHint(QwtPlotItem::RenderAntialiased, true);
#endif
#if 1
  d_curve->setPaintAttribute(QwtPlotCurve::ClipPolygons, false);
#endif
  d_curve->setData(new CurveData(signalData));
  d_curve->attach(this);

  mSignals[signalData] = d_curve;
}

void Plot::removeSignal(SignalData* signalData)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);
  curve->detach();
  delete curve;
  mSignals.remove(signalData);
}

void Plot::setSignalVisible(SignalData* signalData, bool visible)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);

  if (visible)
  {
    curve->attach(this);
  }
  else
  {
    curve->detach();
  }

  this->replot();
}

void Plot::setSignalColor(SignalData* signalData, QColor color)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);
  curve->setPen(QPen(color));
}

void Plot::setPointSize(double pointSize)
{
  foreach (QwtPlotCurve* curve, mSignals.values())
  {
    curve->setStyle(QwtPlotCurve::Dots);
    QPen curvePen = curve->pen();
    curvePen.setWidth(pointSize);
    curve->setPen(curvePen);
  }
}

void Plot::setBackgroundColor(QString color)
{
  if (color == "White")
  {
    mColorMode = 0;
  }
  else if (color == "Black")
  {
    mColorMode = 1;
  }

  this->initBackground();
}

void Plot::initBackground()
{
  if (!d_grid)
  {
    d_grid = new QwtPlotGrid();
    d_grid->enableX(false);
    d_grid->enableXMin(false);
    d_grid->enableY(true);
    d_grid->enableYMin(false);
    d_grid->attach(this);
  }

  if (!d_origin)
  {
    d_origin = new QwtPlotMarker();
    d_origin->setLineStyle(QwtPlotMarker::HLine);
    d_origin->setValue(0.0, 0.0);
    d_origin->attach(this);
  }

  QColor backgroundColor = Qt::white;
  QColor gridColor = Qt::gray;
  if (mColorMode == 1)
  {
    backgroundColor = Qt::black;
    gridColor = QColor(100, 100, 100);
  }

  QPalette pal = canvas()->palette();
  pal.setBrush(QPalette::Window, QBrush(backgroundColor));
  canvas()->setPalette(pal);

  d_grid->setPen(QPen(gridColor, 0.0, Qt::DotLine));
  d_origin->setLinePen(QPen(gridColor, 0.0, Qt::DashLine));
}

void Plot::start()
{
  mStopped = false;
  mMagnifier->setAxisEnabled(QwtPlot::xBottom, mStopped);
}

void Plot::stop()
{
  mStopped = true;
  mMagnifier->setAxisEnabled(QwtPlot::xBottom, mStopped);
}

bool Plot::isStopped()
{
  return mStopped;
}

void Plot::replot()
{
  this->updateTicks();

  // Lock the signal data objects, then plot the data and unlock.
  QList<SignalData*> signalDataList = mSignals.keys();
  foreach (SignalData* signalData, signalDataList)
  {
    signalData->lock();
  }

  QwtPlot::replot();

  foreach (SignalData* signalData, signalDataList)
  {
    signalData->unlock();
  }
}

void Plot::flagAxisSyncRequired()
{
  mAxisSyncRequired = true;
}

double Plot::timeWindow()
{
  return mTimeWindow;
}

void Plot::setTimeWindow(double interval)
{
  if ( interval > 0.0 && interval != mTimeWindow)
  {
    mTimeWindow = interval;
    QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);
    xinterval.setMinValue(xinterval.maxValue() - interval);
    this->setAxisScale(QwtPlot::xBottom, xinterval.minValue(), xinterval.maxValue());
    this->replot();
  }
}

void Plot::setYScale(double scale)
{
  setAxisScale(QwtPlot::yLeft, -scale, scale);
  this->replot();
}

void Plot::setEndTime(double endTime)
{
  QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);
  if (xinterval.maxValue() == endTime)
  {
    return;
  }

  xinterval = QwtInterval(endTime - xinterval.width(), endTime);
  this->setAxisScale(QwtPlot::xBottom, xinterval.minValue(), xinterval.maxValue());
}

void Plot::updateTicks()
{
  this->updateAxes();
  QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);

  // when playing, always use the requested time window
  // when paused, the user may zoom in/out, changing the time window
  if (!this->isStopped())
  {
    xinterval.setMinValue(xinterval.maxValue() - mTimeWindow);
  }

  QwtScaleEngine* engine = axisScaleEngine(QwtPlot::xBottom);
  QwtScaleDiv scaleDiv = engine->divideScale(xinterval.minValue(), xinterval.maxValue(), 0, 0);

  QList<double> majorTicks;
  double majorStep = scaleDiv.range() / 5.0;
  for (int i = 0; i <= 5; ++i)
  {
    majorTicks << scaleDiv.lowerBound() + i*majorStep;
  }
  majorTicks.back() = scaleDiv.upperBound();

  QList<double> minorTicks;
  double minorStep = scaleDiv.range() / 25.0;
  for (int i = 0; i <= 25; ++i)
  {
    minorTicks << scaleDiv.lowerBound() + i*minorStep;
  }
  minorTicks.back() = scaleDiv.upperBound();

  scaleDiv.setTicks(QwtScaleDiv::MajorTick, majorTicks);
  scaleDiv.setTicks(QwtScaleDiv::MinorTick, minorTicks);
  setAxisScaleDiv(QwtPlot::xBottom, scaleDiv);

  if (mAxisSyncRequired)
  {
    emit this->syncXAxisScale(xinterval.minValue(), xinterval.maxValue());
    mAxisSyncRequired = false;
  }
}
<commit_msg>signal scope: disable zoomer middle mouse click, it was clobbering the xaxis scale<commit_after>#include "plot.h"
#include "curvedata.h"
#include "signaldata.h"
#include <qwt_plot_grid.h>
#include <qwt_plot_layout.h>
#include <qwt_plot_canvas.h>
#include <qwt_plot_marker.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_directpainter.h>
#include <qwt_curve_fitter.h>
#include <qwt_painter.h>
#include <qwt_scale_engine.h>
#include <qwt_scale_draw.h>
#include <qwt_plot_zoomer.h>
#include <qwt_plot_panner.h>
#include <qwt_plot_magnifier.h>
#include <qwt_text.h>

#include <qevent.h>

#include <cassert>

class MyPanner : public QObject
{
public:

  QPoint mInitialPos;
  bool mEnabled;
  int mMouseButton;
  int mKeyboardButton;
  Plot* mPlot;

  MyPanner(Plot* plot) : QObject(plot)
  {
    mEnabled = false;
    mMouseButton = Qt::LeftButton;
    mKeyboardButton = Qt::NoButton;
    mPlot = plot;
    mPlot->canvas()->installEventFilter(this);
  }

  bool eventFilter( QObject *object, QEvent *event )
  {
    switch ( event->type() )
    {
      case QEvent::MouseButtonPress:
      {
        widgetMousePressEvent( ( QMouseEvent * )event );
        break;
      }
      case QEvent::MouseMove:
      {
        widgetMouseMoveEvent( ( QMouseEvent * )event );
        break;
      }
      case QEvent::MouseButtonRelease:
      {
        widgetMouseReleaseEvent( ( QMouseEvent * )event );
        break;
      }
    }

    return false;
  }

  void moveCanvas( int dx, int dy )
  {
    if ( dx == 0 && dy == 0 )
        return;

    if (!mPlot->isStopped())
      dx = 0;

    for ( int axis = 0; axis < QwtPlot::axisCnt; axis++ )
    {
      const QwtScaleMap map = mPlot->canvasMap( axis );
      const double p1 = map.transform( mPlot->axisScaleDiv( axis )->lowerBound() );
      const double p2 = map.transform( mPlot->axisScaleDiv( axis )->upperBound() );

      double d1, d2;
      if ( axis == QwtPlot::xBottom || axis == QwtPlot::xTop )
      {
        d1 = map.invTransform( p1 - dx );
        d2 = map.invTransform( p2 - dx );
      }
      else
      {
        d1 = map.invTransform( p1 - dy );
        d2 = map.invTransform( p2 - dy );
      }
      mPlot->setAxisScale( axis, d1, d2 );
    }

    mPlot->flagAxisSyncRequired();
    mPlot->replot();
  }

  void widgetMousePressEvent( QMouseEvent *mouseEvent )
  {
    if (mouseEvent->button() != mMouseButton)
    {
      return;
    }

    if ((mouseEvent->modifiers() & Qt::KeyboardModifierMask) != (mKeyboardButton & Qt::KeyboardModifierMask))
    {
      return;
    }

    mInitialPos = mouseEvent->pos();
    mEnabled = true;
  }

  void widgetMouseMoveEvent( QMouseEvent *mouseEvent )
  {
    if (!mEnabled)
      return;

    QPoint pos = mouseEvent->pos();
    if (pos != mInitialPos)
    {
      moveCanvas(pos.x() - mInitialPos.x(), pos.y() - mInitialPos.y());
      mInitialPos = mouseEvent->pos();
    }
  }

  void widgetMouseReleaseEvent( QMouseEvent *mouseEvent )
  {
    mEnabled = false;
  }

};

class MyScaleDraw : public QwtScaleDraw
{
  virtual QwtText label(double value) const
  {
    return QString::number(value, 'f', 2);
  }
};

class MyZoomer: public QwtPlotZoomer
{
public:

    Plot* mPlot;

    MyZoomer(Plot *plot) : QwtPlotZoomer(plot->canvas())
    {
      mPlot = plot;
      setTrackerMode(AlwaysOn);
    }

    virtual QwtText trackerTextF(const QPointF &pos) const
    {
      QColor bg(Qt::white);
      bg.setAlpha(200);

      QwtText text = QwtPlotZoomer::trackerTextF(pos);
      text.setBackgroundBrush( QBrush( bg ));
      return text;
    }

protected:

    virtual void rescale()
    {
      mPlot->flagAxisSyncRequired();
      QwtPlotZoomer::rescale();
    }

};

class MyMagnifier: public QwtPlotMagnifier
{
public:
    Plot* mPlot;

    MyMagnifier(Plot* plot) : QwtPlotMagnifier(plot->canvas())
    {
      mPlot = plot;
    }

protected:

    // Normally, a value < 1.0 zooms in, a value > 1.0 zooms out.
    // This function is overloaded to invert the magnification direction.
    virtual void rescale( double factor )
    {
      factor = qAbs( factor );
      factor = (1-factor) + 1;

      mPlot->flagAxisSyncRequired();
      this->QwtPlotMagnifier::rescale(factor);
    }

};

Plot::Plot(QWidget *parent):
  QwtPlot(parent),
  d_origin(0),
  d_grid(0),
  mStopped(true),
  mAxisSyncRequired(false),
  mColorMode(0),
  mTimeWindow(10.0)
{
  setAutoReplot(false);

  // The backing store is important, when working with widget
  // overlays ( f.e rubberbands for zooming ).
  // Here we don't have them and the internal
  // backing store of QWidget is good enough.

  canvas()->setPaintAttribute(QwtPlotCanvas::BackingStore, false);

#if defined(Q_WS_X11)
  // Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent
  // works on X11. This has a nice effect on the performance.

  canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true);

  // Disabling the backing store of Qt improves the performance
  // for the direct painter even more, but the canvas becomes
  // a native window of the window system, receiving paint events
  // for resize and expose operations. Those might be expensive
  // when there are many points and the backing store of
  // the canvas is disabled. So in this application
  // we better don't both backing stores.

  if ( canvas()->testPaintAttribute( QwtPlotCanvas::BackingStore ) )
  {
    canvas()->setAttribute(Qt::WA_PaintOnScreen, true);
    canvas()->setAttribute(Qt::WA_NoSystemBackground, true);
  }

#endif

  plotLayout()->setAlignCanvasToScales(true);

  setAxisAutoScale(QwtPlot::xBottom, false);
  setAxisAutoScale(QwtPlot::yLeft, false);

  setAxisTitle(QwtPlot::xBottom, "Time [s]");
  setAxisScale(QwtPlot::xBottom, 0, 10);
  setAxisScale(QwtPlot::yLeft, -4.0, 4.0);

  setAxisScaleDraw(QwtPlot::xBottom, new MyScaleDraw);

  initBackground();

  QwtPlotZoomer* zoomer = new MyZoomer(this);
  zoomer->setMousePattern(QwtEventPattern::QwtEventPattern::MouseSelect1,
      Qt::LeftButton, Qt::ShiftModifier);
  // disable MouseSelect3 action of the zoomer
  zoomer->setMousePattern(QwtEventPattern::MouseSelect3, 0);

  MyPanner *panner = new MyPanner(this);

  // zoom in/out with the wheel
  mMagnifier = new MyMagnifier(this);
  mMagnifier->setMouseButton(Qt::MiddleButton);

  const QColor c(Qt::darkBlue);
  zoomer->setRubberBandPen(c);
  zoomer->setTrackerPen(c);

  this->setMinimumHeight(200);
}

Plot::~Plot()
{

}

void Plot::addSignal(SignalData* signalData, QColor color)
{
  QwtPlotCurve* d_curve = new QwtPlotCurve();
  d_curve->setStyle(QwtPlotCurve::Dots);

  QPen curvePen(color);
  curvePen.setWidth(0);

  d_curve->setPen(curvePen);

#if 1
  d_curve->setRenderHint(QwtPlotItem::RenderAntialiased, true);
#endif
#if 1
  d_curve->setPaintAttribute(QwtPlotCurve::ClipPolygons, false);
#endif
  d_curve->setData(new CurveData(signalData));
  d_curve->attach(this);

  mSignals[signalData] = d_curve;
}

void Plot::removeSignal(SignalData* signalData)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);
  curve->detach();
  delete curve;
  mSignals.remove(signalData);
}

void Plot::setSignalVisible(SignalData* signalData, bool visible)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);

  if (visible)
  {
    curve->attach(this);
  }
  else
  {
    curve->detach();
  }

  this->replot();
}

void Plot::setSignalColor(SignalData* signalData, QColor color)
{
  if (!signalData)
  {
    return;
  }

  QwtPlotCurve* curve = mSignals.value(signalData);
  assert(curve);
  curve->setPen(QPen(color));
}

void Plot::setPointSize(double pointSize)
{
  foreach (QwtPlotCurve* curve, mSignals.values())
  {
    curve->setStyle(QwtPlotCurve::Dots);
    QPen curvePen = curve->pen();
    curvePen.setWidth(pointSize);
    curve->setPen(curvePen);
  }
}

void Plot::setBackgroundColor(QString color)
{
  if (color == "White")
  {
    mColorMode = 0;
  }
  else if (color == "Black")
  {
    mColorMode = 1;
  }

  this->initBackground();
}

void Plot::initBackground()
{
  if (!d_grid)
  {
    d_grid = new QwtPlotGrid();
    d_grid->enableX(false);
    d_grid->enableXMin(false);
    d_grid->enableY(true);
    d_grid->enableYMin(false);
    d_grid->attach(this);
  }

  if (!d_origin)
  {
    d_origin = new QwtPlotMarker();
    d_origin->setLineStyle(QwtPlotMarker::HLine);
    d_origin->setValue(0.0, 0.0);
    d_origin->attach(this);
  }

  QColor backgroundColor = Qt::white;
  QColor gridColor = Qt::gray;
  if (mColorMode == 1)
  {
    backgroundColor = Qt::black;
    gridColor = QColor(100, 100, 100);
  }

  QPalette pal = canvas()->palette();
  pal.setBrush(QPalette::Window, QBrush(backgroundColor));
  canvas()->setPalette(pal);

  d_grid->setPen(QPen(gridColor, 0.0, Qt::DotLine));
  d_origin->setLinePen(QPen(gridColor, 0.0, Qt::DashLine));
}

void Plot::start()
{
  mStopped = false;
  mMagnifier->setAxisEnabled(QwtPlot::xBottom, mStopped);
}

void Plot::stop()
{
  mStopped = true;
  mMagnifier->setAxisEnabled(QwtPlot::xBottom, mStopped);
}

bool Plot::isStopped()
{
  return mStopped;
}

void Plot::replot()
{
  this->updateTicks();

  // Lock the signal data objects, then plot the data and unlock.
  QList<SignalData*> signalDataList = mSignals.keys();
  foreach (SignalData* signalData, signalDataList)
  {
    signalData->lock();
  }

  QwtPlot::replot();

  foreach (SignalData* signalData, signalDataList)
  {
    signalData->unlock();
  }
}

void Plot::flagAxisSyncRequired()
{
  mAxisSyncRequired = true;
}

double Plot::timeWindow()
{
  return mTimeWindow;
}

void Plot::setTimeWindow(double interval)
{
  if ( interval > 0.0 && interval != mTimeWindow)
  {
    mTimeWindow = interval;
    QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);
    xinterval.setMinValue(xinterval.maxValue() - interval);
    this->setAxisScale(QwtPlot::xBottom, xinterval.minValue(), xinterval.maxValue());
    this->replot();
  }
}

void Plot::setYScale(double scale)
{
  setAxisScale(QwtPlot::yLeft, -scale, scale);
  this->replot();
}

void Plot::setEndTime(double endTime)
{
  QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);
  if (xinterval.maxValue() == endTime)
  {
    return;
  }

  xinterval = QwtInterval(endTime - xinterval.width(), endTime);
  this->setAxisScale(QwtPlot::xBottom, xinterval.minValue(), xinterval.maxValue());
}

void Plot::updateTicks()
{
  this->updateAxes();
  QwtInterval xinterval = this->axisInterval(QwtPlot::xBottom);

  // when playing, always use the requested time window
  // when paused, the user may zoom in/out, changing the time window
  if (!this->isStopped())
  {
    xinterval.setMinValue(xinterval.maxValue() - mTimeWindow);
  }

  QwtScaleEngine* engine = axisScaleEngine(QwtPlot::xBottom);
  QwtScaleDiv scaleDiv = engine->divideScale(xinterval.minValue(), xinterval.maxValue(), 0, 0);

  QList<double> majorTicks;
  double majorStep = scaleDiv.range() / 5.0;
  for (int i = 0; i <= 5; ++i)
  {
    majorTicks << scaleDiv.lowerBound() + i*majorStep;
  }
  majorTicks.back() = scaleDiv.upperBound();

  QList<double> minorTicks;
  double minorStep = scaleDiv.range() / 25.0;
  for (int i = 0; i <= 25; ++i)
  {
    minorTicks << scaleDiv.lowerBound() + i*minorStep;
  }
  minorTicks.back() = scaleDiv.upperBound();

  scaleDiv.setTicks(QwtScaleDiv::MajorTick, majorTicks);
  scaleDiv.setTicks(QwtScaleDiv::MinorTick, minorTicks);
  setAxisScaleDiv(QwtPlot::xBottom, scaleDiv);

  if (mAxisSyncRequired)
  {
    emit this->syncXAxisScale(xinterval.minValue(), xinterval.maxValue());
    mAxisSyncRequired = false;
  }
}
<|endoftext|>


<commit_before>/************************************************
 * Copyright (c) IBM Corp. 2014
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *************************************************/

/*
 * skv_mutex.hpp
 *
 *  Created on: May 20, 2014
 *      Author: lschneid
 */

#ifndef SKV_MUTEX_HPP_
#define SKV_MUTEX_HPP_

#ifndef SKV_MUTEX_LOG
#define SKV_MUTEX_LOG ( 0 )
#endif

/* This is a dumb impl to encapsulate locking via pthread_mutex to work around old compilers not able to cope with C++11
 * This could be removed once we decide to require C++11 compiler support for whole SKV */
class skv_mutex_t {
  pthread_spinlock_t mMutex;
#if (SKV_MUTEX_LOG != 0)
  int mLogThisMutex;
#else
#define mLogThisMutex ( 0 )
#endif

public:
#if (SKV_MUTEX_LOG == 0)
  skv_mutex_t( const pthread_mutexattr_t *aAttributes = NULL )
#else
  skv_mutex_t( const pthread_mutexattr_t *aAttributes = NULL, const int aLogThisMutex = 0 )
#endif
  {
#if (SKV_MUTEX_LOG != 0)
  mLogThisMutex = aLogThisMutex;
#endif
    pthread_spin_init( &mMutex, 0 );
    BegLogLine( SKV_MUTEX_LOG ) << "Initialized lock: 0x" << (void*)&mMutex << EndLogLine;
  }
  ~skv_mutex_t()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "Destroying lock: 0x" << (void*)&mMutex << EndLogLine;
    pthread_spin_destroy( &mMutex );
  }
  inline int lock()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "About to lock: 0x" << (void*)&mMutex << EndLogLine;
    return pthread_spin_lock( &mMutex );
  }
  inline int unlock()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "Unlocking: 0x" << (void*)&mMutex << EndLogLine;
    return pthread_spin_unlock( &mMutex );
  }
  inline int trylock()
  {
    return pthread_spin_trylock( &mMutex );
  }

#if (SKV_MUTEX_LOG != 0)
  inline void init( int aLogThisMutex )
  {
    mLogThisMutex = aLogThisMutex;
  }
#else
  inline void init( int aLogThisMutex ) {}
#endif
};

#endif /* SKV_MUTEX_HPP_ */
<commit_msg>Standard skv mutex<commit_after>/************************************************
 * Copyright (c) IBM Corp. 2014
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *************************************************/

/*
 * skv_mutex.hpp
 *
 *  Created on: May 20, 2014
 *      Author: lschneid
 */

#ifndef SKV_MUTEX_HPP_
#define SKV_MUTEX_HPP_

#ifndef SKV_MUTEX_LOG
#define SKV_MUTEX_LOG ( 0 )
#endif

/* This is a dumb impl to encapsulate locking via pthread_mutex to work around old compilers not able to cope with C++11
 * This could be removed once we decide to require C++11 compiler support for whole SKV */
class skv_mutex_t {
  pthread_mutex_t mMutex;
#if (SKV_MUTEX_LOG != 0)
  int mLogThisMutex;
#else
#define mLogThisMutex ( 0 )
#endif

public:
#if (SKV_MUTEX_LOG == 0)
  skv_mutex_t( const pthread_mutexattr_t *aAttributes = NULL )
#else
  skv_mutex_t( const pthread_mutexattr_t *aAttributes = NULL, const int aLogThisMutex = 0 )
#endif
  {
#if (SKV_MUTEX_LOG != 0)
  mLogThisMutex = aLogThisMutex;
#endif
    pthread_mutex_init( &mMutex, 0 );
    BegLogLine( SKV_MUTEX_LOG ) << "Initialized lock: 0x" << (void*)&mMutex << EndLogLine;
  }
  ~skv_mutex_t()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "Destroying lock: 0x" << (void*)&mMutex << EndLogLine;
    pthread_mutex_destroy( &mMutex );
  }
  inline int lock()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "About to lock: 0x" << (void*)&mMutex << EndLogLine;
    return pthread_mutex_lock( &mMutex );
  }
  inline int unlock()
  {
    BegLogLine( SKV_MUTEX_LOG && (mLogThisMutex) ) << "Unlocking: 0x" << (void*)&mMutex << EndLogLine;
    return pthread_mutex_unlock( &mMutex );
  }
  inline int trylock()
  {
    return pthread_mutex_trylock( &mMutex );
  }

#if (SKV_MUTEX_LOG != 0)
  inline void init( int aLogThisMutex )
  {
    mLogThisMutex = aLogThisMutex;
  }
#else
  inline void init( int aLogThisMutex ) {}
#endif
};

#endif /* SKV_MUTEX_HPP_ */
<|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Author: Matevz Tadel 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_REveCaloData
#define ROOT_REveCaloData

#include <vector>
#include "ROOT/REveElement.hxx"

#include "TMath.h"

class TH2F;
class TAxis;
class THStack;

namespace ROOT {
namespace Experimental {

class REveCaloData: public REveElement,
                    public REveAuntAsList
{
public:
   struct SliceInfo_t
   {
      TString  fName;      // Name of the slice, eg. ECAL, HCAL.
      Float_t  fThreshold; // Only display towers with higher energy.
      Color_t  fColor;     // Color used to draw this longitudinal slice.
      Color_t  fTransparency; // Transparency used to draw this longitudinal slice.

      SliceInfo_t(): fName(""), fThreshold(0), fColor(kRed), fTransparency(0) {}

      virtual ~SliceInfo_t() {}

      void Setup(const char* name, Float_t threshold, Color_t col, Char_t transp = 101)
      {
         fName      = name;
         fThreshold = threshold;
         fColor     = col;
         if (transp <= 100) fTransparency = transp;
      };
   };

   typedef std::vector<SliceInfo_t>           vSliceInfo_t;
   typedef std::vector<SliceInfo_t>::iterator vSliceInfo_i;

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

   struct CellId_t
   {
      // Cell ID inner structure.

      Int_t fTower;
      Int_t fSlice;

      Float_t fFraction;

      CellId_t() : fTower(0), fSlice(0), fFraction(0) {}
      CellId_t(Int_t t, Int_t s, Float_t f=1.0f) : fTower(t), fSlice(s), fFraction(f) {}

      bool operator<(const CellId_t& o) const
      { return (fTower == o.fTower) ? fSlice < o.fSlice : fTower < o.fTower; }
   };

   struct CellGeom_t
   {
      // Cell geometry inner structure.

      Float_t fPhiMin;
      Float_t fPhiMax;
      Float_t fEtaMin;
      Float_t fEtaMax;

      Float_t fThetaMin; // cached
      Float_t fThetaMax; // cached

      CellGeom_t(): fPhiMin(0), fPhiMax(0), fEtaMin(0), fEtaMax(0), fThetaMin(0), fThetaMax(0) {}
      CellGeom_t(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax) {Configure(etaMin, etaMax, phiMin, phiMax);}
      virtual ~CellGeom_t() {}

      void Configure(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax);

      Float_t EtaMin()   const { return fEtaMin; }
      Float_t EtaMax()   const { return fEtaMax; }
      Float_t Eta()      const { return (fEtaMin+fEtaMax)*0.5f; }
      Float_t EtaDelta() const { return fEtaMax-fEtaMin; }

      Float_t PhiMin()   const { return fPhiMin; }
      Float_t PhiMax()   const { return fPhiMax; }
      Float_t Phi()      const { return (fPhiMin+fPhiMax)*0.5f; }
      Float_t PhiDelta() const { return fPhiMax-fPhiMin; }

      Float_t ThetaMin() const { return fThetaMin; }
      Float_t ThetaMax() const { return fThetaMax; }
      Float_t Theta() const { return (fThetaMax+fThetaMin)*0.5f; }
      Float_t ThetaDelta() const { return fThetaMax-fThetaMin; }

      Bool_t  IsUpperRho() const
      {
         const Float_t phi = Phi();
         return ((phi > 0 && phi <= TMath::Pi()) || phi < - TMath::Pi());
      }

      virtual void  Dump() const;
   };

   struct CellData_t : public CellGeom_t
   {
      // Cell data inner structure.

      Float_t fValue;

      CellData_t() : CellGeom_t(), fValue(0) {}
      virtual ~CellData_t() {}

      Float_t Value(Bool_t) const;
      virtual void Dump() const;
   };

   struct RebinData_t
   {
      Int_t fNSlices;

      std::vector<Float_t> fSliceData;
      std::vector<Int_t>   fBinData;

      Float_t* GetSliceVals(Int_t bin);

      void Clear()
      {
         fSliceData.clear();
         fBinData.clear();
      }
   };

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

   typedef std::vector<CellId_t>               vCellId_t;
   typedef std::vector<CellId_t>::iterator     vCellId_i;

   typedef std::vector<CellGeom_t>             vCellGeom_t;
   typedef std::vector<CellGeom_t>::iterator   vCellGeom_i;
   typedef std::vector<CellGeom_t>::const_iterator   vCellGeom_ci;

private:
   REveCaloData& operator=(const REveCaloData&) = delete;

protected:
   vSliceInfo_t fSliceInfos;

   TAxis*       fEtaAxis;
   TAxis*       fPhiAxis;

   Bool_t       fWrapTwoPi;

   Float_t      fMaxValEt; // cached
   Float_t      fMaxValE;  // cached

   Float_t      fEps;

   vCellId_t    fCellsSelected;
   vCellId_t    fCellsHighlighted;

   int          fSelectionSecondarySelectIdx;
   int          fHighlightSecondarySelectIdx;

public:
   REveCaloData(const char* n="REveCaloData", const char* t="");
   virtual ~REveCaloData() {}

   virtual void UnSelected();
   virtual void UnHighlighted();

   std::string GetHighlightTooltip() const override;

   void    FillImpliedSelectedSet(Set_t& impSelSet) override;

   virtual void    GetCellList(Float_t etaMin, Float_t etaMax,
                               Float_t phi,    Float_t phiRng,
                               vCellId_t &out) const = 0;

   vCellId_t&      GetCellsSelected()    { return fCellsSelected; }
   vCellId_t&      GetCellsHighlighted() { return fCellsHighlighted; }
   void            PrintCellsSelected();
   void            ProcessSelection(vCellId_t& sel_cells, UInt_t selectionId, Bool_t multi);

   virtual void    Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const = 0;

   virtual void    GetCellData(const CellId_t &id, CellData_t& data) const = 0;

   virtual void    InvalidateUsersCellIdCache();
   virtual void    DataChanged();
   virtual void    CellSelectionChanged(UInt_t selectionId, Int_t secSel);

   Int_t           GetNSlices()    const { return fSliceInfos.size(); }
   SliceInfo_t&    RefSliceInfo(Int_t s) { return fSliceInfos[s]; }
   void            SetSliceThreshold(Int_t slice, Float_t threshold);
   Float_t         GetSliceThreshold(Int_t slice) const;
   void            SetSliceColor(Int_t slice, Color_t col);
   Color_t         GetSliceColor(Int_t slice) const;
   void            SetSliceTransparency(Int_t slice, Char_t t);
   Char_t          GetSliceTransparency(Int_t slice) const;

   virtual void    GetEtaLimits(Double_t &min, Double_t &max) const = 0;

   virtual void    GetPhiLimits(Double_t &min, Double_t &max) const = 0;

   virtual Float_t GetMaxVal(Bool_t et) const { return et ? fMaxValEt : fMaxValE; }
   Bool_t  Empty() const { return fMaxValEt < 1e-5; }

   virtual TAxis*  GetEtaBins()    const { return fEtaAxis; }
   virtual void    SetEtaBins(TAxis* ax) { fEtaAxis=ax; }

   virtual TAxis*  GetPhiBins()    const { return fPhiAxis; }
   virtual void    SetPhiBins(TAxis* ax) { fPhiAxis=ax; }

   virtual Float_t GetEps()      const { return fEps; }
   virtual void    SetEps(Float_t eps) { fEps=eps; }

   Bool_t   GetWrapTwoPi() const { return fWrapTwoPi; }
   void     SetWrapTwoPi(Bool_t w) { fWrapTwoPi=w; }

   Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override;

   static  Float_t EtaToTheta(Float_t eta);
};

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

class REveCaloDataVec: public REveCaloData
{

private:
   REveCaloDataVec& operator=(const REveCaloDataVec&) = delete;

protected:
   typedef std::vector<Float_t>               vFloat_t;
   typedef std::vector<Float_t>::iterator     vFloat_i;

   typedef std::vector<vFloat_t>              vvFloat_t;
   typedef std::vector<vFloat_t>::iterator    vvFloat_i;

   vvFloat_t   fSliceVec;
   vCellGeom_t fGeomVec;

   Int_t       fTower; // current tower

   Float_t     fEtaMin;
   Float_t     fEtaMax;

   Float_t     fPhiMin;
   Float_t     fPhiMax;

public:
   REveCaloDataVec(Int_t nslices);
   virtual ~REveCaloDataVec();

   Int_t AddSlice();
   Int_t AddTower(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax);
   void  FillSlice(Int_t slice, Float_t value);
   void  FillSlice(Int_t slice, Int_t tower, Float_t value);

   Int_t GetNCells() { return fGeomVec.size(); }
   std::vector<Float_t>&  GetSliceVals(Int_t slice) { return fSliceVec[slice]; }
   std::vector<REveCaloData::CellGeom_t>& GetCellGeom() { return fGeomVec; }

   virtual void GetCellList(Float_t etaMin, Float_t etaMax,
                            Float_t phi,    Float_t phiRng,
                            vCellId_t &out) const;

   virtual void Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const;

   virtual void GetCellData(const REveCaloData::CellId_t &id, REveCaloData::CellData_t& data) const;
   virtual void GetEtaLimits(Double_t &min, Double_t &max) const { min=fEtaMin, max=fEtaMax;}
   virtual void GetPhiLimits(Double_t &min, Double_t &max) const { min=fPhiMin; max=fPhiMax;}

   virtual void  DataChanged();
   void          SetAxisFromBins(Double_t epsX=0.001, Double_t epsY=0.001);
};

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

class REveCaloDataHist: public REveCaloData
{
private:
   REveCaloDataHist& operator=(const REveCaloDataHist&) = delete;

protected:
   THStack*    fHStack;

public:
   REveCaloDataHist();
   virtual ~REveCaloDataHist();

   virtual void GetCellList( Float_t etaMin, Float_t etaMax,
                             Float_t phi, Float_t phiRng, vCellId_t &out) const;

   virtual void Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const;

   virtual void GetCellData(const REveCaloData::CellId_t &id, REveCaloData::CellData_t& data) const;

   virtual void GetEtaLimits(Double_t &min, Double_t &max) const;
   virtual void GetPhiLimits(Double_t &min, Double_t &max) const;

   virtual void DataChanged();

   THStack* GetStack() { return fHStack; }

   TH2F*    GetHist(Int_t slice) const;

   Int_t   AddHistogram(TH2F* hist);
};

} // namespace Experimental
} // namespace ROOT
#endif

<commit_msg>Remove trailing white space<commit_after>// @(#)root/eve:$Id$
// Author: Matevz Tadel 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_REveCaloData
#define ROOT_REveCaloData

#include <vector>
#include "ROOT/REveElement.hxx"

#include "TMath.h"

class TH2F;
class TAxis;
class THStack;

namespace ROOT {
namespace Experimental {

class REveCaloData: public REveElement,
                    public REveAuntAsList
{
public:
   struct SliceInfo_t
   {
      TString  fName;      // Name of the slice, eg. ECAL, HCAL.
      Float_t  fThreshold; // Only display towers with higher energy.
      Color_t  fColor;     // Color used to draw this longitudinal slice.
      Color_t  fTransparency; // Transparency used to draw this longitudinal slice.

      SliceInfo_t(): fName(""), fThreshold(0), fColor(kRed), fTransparency(0) {}

      virtual ~SliceInfo_t() {}

      void Setup(const char* name, Float_t threshold, Color_t col, Char_t transp = 101)
      {
         fName      = name;
         fThreshold = threshold;
         fColor     = col;
         if (transp <= 100) fTransparency = transp;
      };
   };

   typedef std::vector<SliceInfo_t>           vSliceInfo_t;
   typedef std::vector<SliceInfo_t>::iterator vSliceInfo_i;

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

   struct CellId_t
   {
      // Cell ID inner structure.

      Int_t fTower;
      Int_t fSlice;

      Float_t fFraction;

      CellId_t() : fTower(0), fSlice(0), fFraction(0) {}
      CellId_t(Int_t t, Int_t s, Float_t f=1.0f) : fTower(t), fSlice(s), fFraction(f) {}

      bool operator<(const CellId_t& o) const
      { return (fTower == o.fTower) ? fSlice < o.fSlice : fTower < o.fTower; }
   };

   struct CellGeom_t
   {
      // Cell geometry inner structure.

      Float_t fPhiMin;
      Float_t fPhiMax;
      Float_t fEtaMin;
      Float_t fEtaMax;

      Float_t fThetaMin; // cached
      Float_t fThetaMax; // cached

      CellGeom_t(): fPhiMin(0), fPhiMax(0), fEtaMin(0), fEtaMax(0), fThetaMin(0), fThetaMax(0) {}
      CellGeom_t(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax) {Configure(etaMin, etaMax, phiMin, phiMax);}
      virtual ~CellGeom_t() {}

      void Configure(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax);

      Float_t EtaMin()   const { return fEtaMin; }
      Float_t EtaMax()   const { return fEtaMax; }
      Float_t Eta()      const { return (fEtaMin+fEtaMax)*0.5f; }
      Float_t EtaDelta() const { return fEtaMax-fEtaMin; }

      Float_t PhiMin()   const { return fPhiMin; }
      Float_t PhiMax()   const { return fPhiMax; }
      Float_t Phi()      const { return (fPhiMin+fPhiMax)*0.5f; }
      Float_t PhiDelta() const { return fPhiMax-fPhiMin; }

      Float_t ThetaMin() const { return fThetaMin; }
      Float_t ThetaMax() const { return fThetaMax; }
      Float_t Theta() const { return (fThetaMax+fThetaMin)*0.5f; }
      Float_t ThetaDelta() const { return fThetaMax-fThetaMin; }

      Bool_t  IsUpperRho() const
      {
         const Float_t phi = Phi();
         return ((phi > 0 && phi <= TMath::Pi()) || phi < - TMath::Pi());
      }

      virtual void  Dump() const;
   };

   struct CellData_t : public CellGeom_t
   {
      // Cell data inner structure.

      Float_t fValue;

      CellData_t() : CellGeom_t(), fValue(0) {}
      virtual ~CellData_t() {}

      Float_t Value(Bool_t) const;
      virtual void Dump() const;
   };

   struct RebinData_t
   {
      Int_t fNSlices;

      std::vector<Float_t> fSliceData;
      std::vector<Int_t>   fBinData;

      Float_t* GetSliceVals(Int_t bin);

      void Clear()
      {
         fSliceData.clear();
         fBinData.clear();
      }
   };

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

   typedef std::vector<CellId_t>               vCellId_t;
   typedef std::vector<CellId_t>::iterator     vCellId_i;

   typedef std::vector<CellGeom_t>             vCellGeom_t;
   typedef std::vector<CellGeom_t>::iterator   vCellGeom_i;
   typedef std::vector<CellGeom_t>::const_iterator   vCellGeom_ci;

private:
   REveCaloData& operator=(const REveCaloData&) = delete;

protected:
   vSliceInfo_t fSliceInfos;

   TAxis*       fEtaAxis;
   TAxis*       fPhiAxis;

   Bool_t       fWrapTwoPi;

   Float_t      fMaxValEt; // cached
   Float_t      fMaxValE;  // cached

   Float_t      fEps;

   vCellId_t    fCellsSelected;
   vCellId_t    fCellsHighlighted;

   int          fSelectionSecondarySelectIdx;
   int          fHighlightSecondarySelectIdx;

public:
   REveCaloData(const char* n="REveCaloData", const char* t="");
   virtual ~REveCaloData() {}

   virtual void UnSelected();
   virtual void UnHighlighted();

   std::string GetHighlightTooltip() const override;

   void    FillImpliedSelectedSet(Set_t& impSelSet) override;

   virtual void    GetCellList(Float_t etaMin, Float_t etaMax,
                               Float_t phi,    Float_t phiRng,
                               vCellId_t &out) const = 0;

   vCellId_t&      GetCellsSelected()    { return fCellsSelected; }
   vCellId_t&      GetCellsHighlighted() { return fCellsHighlighted; }
   void            PrintCellsSelected();
   void            ProcessSelection(vCellId_t& sel_cells, UInt_t selectionId, Bool_t multi);

   virtual void    Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const = 0;

   virtual void    GetCellData(const CellId_t &id, CellData_t& data) const = 0;

   virtual void    InvalidateUsersCellIdCache();
   virtual void    DataChanged();
   virtual void    CellSelectionChanged(UInt_t selectionId, Int_t secSel);

   Int_t           GetNSlices()    const { return fSliceInfos.size(); }
   SliceInfo_t&    RefSliceInfo(Int_t s) { return fSliceInfos[s]; }
   void            SetSliceThreshold(Int_t slice, Float_t threshold);
   Float_t         GetSliceThreshold(Int_t slice) const;
   void            SetSliceColor(Int_t slice, Color_t col);
   Color_t         GetSliceColor(Int_t slice) const;
   void            SetSliceTransparency(Int_t slice, Char_t t);
   Char_t          GetSliceTransparency(Int_t slice) const;

   virtual void    GetEtaLimits(Double_t &min, Double_t &max) const = 0;

   virtual void    GetPhiLimits(Double_t &min, Double_t &max) const = 0;

   virtual Float_t GetMaxVal(Bool_t et) const { return et ? fMaxValEt : fMaxValE; }
   Bool_t  Empty() const { return fMaxValEt < 1e-5; }

   virtual TAxis*  GetEtaBins()    const { return fEtaAxis; }
   virtual void    SetEtaBins(TAxis* ax) { fEtaAxis=ax; }

   virtual TAxis*  GetPhiBins()    const { return fPhiAxis; }
   virtual void    SetPhiBins(TAxis* ax) { fPhiAxis=ax; }

   virtual Float_t GetEps()      const { return fEps; }
   virtual void    SetEps(Float_t eps) { fEps=eps; }

   Bool_t   GetWrapTwoPi() const { return fWrapTwoPi; }
   void     SetWrapTwoPi(Bool_t w) { fWrapTwoPi=w; }

   Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override;

   static  Float_t EtaToTheta(Float_t eta);
};

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

class REveCaloDataVec: public REveCaloData
{

private:
   REveCaloDataVec& operator=(const REveCaloDataVec&) = delete;

protected:
   typedef std::vector<Float_t>               vFloat_t;
   typedef std::vector<Float_t>::iterator     vFloat_i;

   typedef std::vector<vFloat_t>              vvFloat_t;
   typedef std::vector<vFloat_t>::iterator    vvFloat_i;

   vvFloat_t   fSliceVec;
   vCellGeom_t fGeomVec;

   Int_t       fTower; // current tower

   Float_t     fEtaMin;
   Float_t     fEtaMax;

   Float_t     fPhiMin;
   Float_t     fPhiMax;

public:
   REveCaloDataVec(Int_t nslices);
   virtual ~REveCaloDataVec();

   Int_t AddSlice();
   Int_t AddTower(Float_t etaMin, Float_t etaMax, Float_t phiMin, Float_t phiMax);
   void  FillSlice(Int_t slice, Float_t value);
   void  FillSlice(Int_t slice, Int_t tower, Float_t value);

   Int_t GetNCells() { return fGeomVec.size(); }
   std::vector<Float_t>&  GetSliceVals(Int_t slice) { return fSliceVec[slice]; }
   std::vector<REveCaloData::CellGeom_t>& GetCellGeom() { return fGeomVec; }

   virtual void GetCellList(Float_t etaMin, Float_t etaMax,
                            Float_t phi,    Float_t phiRng,
                            vCellId_t &out) const;

   virtual void Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const;

   virtual void GetCellData(const REveCaloData::CellId_t &id, REveCaloData::CellData_t& data) const;
   virtual void GetEtaLimits(Double_t &min, Double_t &max) const { min=fEtaMin, max=fEtaMax;}
   virtual void GetPhiLimits(Double_t &min, Double_t &max) const { min=fPhiMin; max=fPhiMax;}

   virtual void  DataChanged();
   void          SetAxisFromBins(Double_t epsX=0.001, Double_t epsY=0.001);
};

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

class REveCaloDataHist: public REveCaloData
{
private:
   REveCaloDataHist& operator=(const REveCaloDataHist&) = delete;

protected:
   THStack*    fHStack;

public:
   REveCaloDataHist();
   virtual ~REveCaloDataHist();

   virtual void GetCellList( Float_t etaMin, Float_t etaMax,
                             Float_t phi, Float_t phiRng, vCellId_t &out) const;

   virtual void Rebin(TAxis *ax, TAxis *ay, vCellId_t &in, Bool_t et, RebinData_t &out) const;

   virtual void GetCellData(const REveCaloData::CellId_t &id, REveCaloData::CellData_t& data) const;

   virtual void GetEtaLimits(Double_t &min, Double_t &max) const;
   virtual void GetPhiLimits(Double_t &min, Double_t &max) const;

   virtual void DataChanged();

   THStack* GetStack() { return fHStack; }

   TH2F*    GetHist(Int_t slice) const;

   Int_t   AddHistogram(TH2F* hist);
};

} // namespace Experimental
} // namespace ROOT
#endif

<|endoftext|>


<commit_before>// @(#)root/eve:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_REveDigitSet
#define ROOT_REveDigitSet

#include "TNamed.h"
#include "TAtt3D.h"
#include "TAttBBox.h"

#include "ROOT/REveUtil.hxx"
#include "ROOT/REveElement.hxx"
#include "ROOT/REveFrameBox.hxx"
#include "ROOT/REveRGBAPalette.hxx"
#include "ROOT/REveChunkManager.hxx"
#include "ROOT/REveSecondarySelectable.hxx"

class TRefArray;

namespace ROOT {
namespace Experimental {

class REveDigitSet : public REveElement,
                     public TAtt3D,
                     public TAttBBox,
                     public REveSecondarySelectable
{
   friend class REveDigitSetEditor;
   friend class REveDigitSetGL;

   REveDigitSet(const REveDigitSet&);            // Not implemented
   REveDigitSet& operator=(const REveDigitSet&); // Not implemented

public:
   enum ERenderMode_e { kRM_AsIs, kRM_Line, kRM_Fill };

   typedef void (*Callback_foo)(REveDigitSet*, Int_t, TObject*);
   typedef TString (*TooltipCB_foo)(REveDigitSet*, Int_t);

   struct DigitBase_t
   {
      // Base-class for digit representation classes.

      Int_t  fValue;    // signal value of a digit (can be direct RGBA color)
      void  *fUserData; // user-data for given digit

      DigitBase_t(Int_t v=0) : fValue(v), fUserData(0) {}
   };

protected:
   TRefArray        *fDigitIds;       //  Array holding references to external objects.

   Int_t             fDefaultValue;   //  Default signal value.
   Bool_t            fValueIsColor;   //  Interpret signal value as RGBA color.
   Bool_t            fSingleColor;    //  Use the same color for all digits.
   Bool_t            fAntiFlick;      // Make extra render pass to avoid flickering when quads are too small.
   Bool_t            fOwnIds;         //  Flag specifying if id-objects are owned by the REveDigitSet.
   REveChunkManager  fPlex;           //  Container of digit data.
   DigitBase_t*      fLastDigit;      //! The last / current digit added to collection.
   Int_t             fLastIdx;        //! The last / current idx added to collection.

   Color_t           fColor;          //  Color used for frame (or all digis with single-color).
   REveFrameBox*     fFrame;          //  Pointer to frame structure.
   REveRGBAPalette*  fPalette;        //  Pointer to signal-color palette.
   ERenderMode_e     fRenderMode;     //  Render mode: as-is / line / filled.
   Bool_t            fSelectViaFrame; //  Allow selection via frame.
   Bool_t            fHighlightFrame; //  Highlight frame when object is selected.
   Bool_t            fDisableLighting;//  Disable lighting for rendering.
   Bool_t            fHistoButtons;   //  Show histogram buttons in object editor.

   Bool_t            fEmitSignals;    //  Emit signals on secondary-select.
   Callback_foo      fCallbackFoo;    //! Additional function to call on secondary-select.
   TooltipCB_foo     fTooltipCBFoo;   //! Function providing highlight tooltips when always-sec-select is active.

   DigitBase_t* NewDigit();
   void         ReleaseIds();

public:
   REveDigitSet(const char* n="REveDigitSet", const char* t="");
   virtual ~REveDigitSet();

   void   UseSingleColor();

   Bool_t GetAntiFlick() const   { return fAntiFlick; }
   void   SetAntiFlick(Bool_t f) { fAntiFlick = f; }

   virtual void SetMainColor(Color_t color) override;

   /*
   virtual void UnSelected();
   virtual void UnHighlighted();

   using REveElement::GetHighlightTooltip;
   virtual TString GetHighlightTooltip();
   */

   // Implemented in sub-classes:
   // virtual void Reset(EQuadType_e quadType, Bool_t valIsCol, Int_t chunkSize);

   void RefitPlex();
   void ScanMinMaxValues(Int_t& min, Int_t& max);

   // --------------------------------

   void SetCurrentDigit(Int_t idx);

   void DigitValue(Int_t value);
   void DigitColor(Color_t ci);
   void DigitColor(Color_t ci, Char_t transparency);
   void DigitColor(UChar_t r, UChar_t g, UChar_t b, UChar_t a=255);
   void DigitColor(UChar_t* rgba);

   Bool_t GetOwnIds() const     { return fOwnIds; }
   void   SetOwnIds(Bool_t o)   { fOwnIds = o; }

   void   DigitId(TObject* id);
   void   DigitUserData(void* ud);

   void   DigitId(Int_t n, TObject* id);
   void   DigitUserData(Int_t n, void* ud);

   DigitBase_t* GetDigit(Int_t n) const { return (DigitBase_t*) fPlex.Atom(n); }
   TObject*     GetId(Int_t n) const;
   void*        GetUserData(Int_t n) const;
   using REveElement::GetUserData;

   // --------------------------------

   // Implemented in subclasses:
   // virtual void ComputeBBox();
   /*
   virtual void Paint(Option_t* option="");

   virtual void DigitSelected(Int_t idx);
   virtual void SecSelected(REveDigitSet* qs, Int_t idx); // *SIGNAL*
   */
   // --------------------------------

   REveChunkManager* GetPlex() { return &fPlex; }

   REveFrameBox* GetFrame() const { return fFrame; }
   void          SetFrame(REveFrameBox* b);

   Bool_t GetSelectViaFrame() const    { return fSelectViaFrame; }
   void   SetSelectViaFrame(Bool_t sf) { fSelectViaFrame = sf; }

   Bool_t GetHighlightFrame() const    { return fHighlightFrame; }
   void   SetHighlightFrame(Bool_t hf) { fHighlightFrame = hf; }

   Bool_t GetValueIsColor()  const { return fValueIsColor; }

   REveRGBAPalette* GetPalette() const { return fPalette; }
   void             SetPalette(REveRGBAPalette* p);
   REveRGBAPalette* AssertPalette();

   ERenderMode_e  GetRenderMode()           const { return fRenderMode; }
   void           SetRenderMode(ERenderMode_e rm) { fRenderMode = rm; }

   Bool_t GetDisableLighting() const   { return fDisableLighting; }
   void   SetDisableLighting(Bool_t l) { fDisableLighting = l; }

   Bool_t GetHistoButtons() const   { return fHistoButtons; }
   void   SetHistoButtons(Bool_t f) { fHistoButtons = f; }

   Bool_t GetEmitSignals() const   { return fEmitSignals; }
   void   SetEmitSignals(Bool_t f) { fEmitSignals = f; }

   Callback_foo GetCallbackFoo()         const { return fCallbackFoo; }
   void         SetCallbackFoo(Callback_foo f) { fCallbackFoo = f; }

   TooltipCB_foo GetTooltipCBFoo()          const { return fTooltipCBFoo; }
   void          SetTooltipCBFoo(TooltipCB_foo f) { fTooltipCBFoo = f; }

   Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override;
};

} // namespace Experimental
} // namespace ROOT
#endif
<commit_msg>Add missing initialization of fUserData<commit_after>// @(#)root/eve:$Id$
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_REveDigitSet
#define ROOT_REveDigitSet

#include "TNamed.h"
#include "TAtt3D.h"
#include "TAttBBox.h"

#include "ROOT/REveUtil.hxx"
#include "ROOT/REveElement.hxx"
#include "ROOT/REveFrameBox.hxx"
#include "ROOT/REveRGBAPalette.hxx"
#include "ROOT/REveChunkManager.hxx"
#include "ROOT/REveSecondarySelectable.hxx"

class TRefArray;

namespace ROOT {
namespace Experimental {

class REveDigitSet : public REveElement,
                     public TAtt3D,
                     public TAttBBox,
                     public REveSecondarySelectable
{
   friend class REveDigitSetEditor;
   friend class REveDigitSetGL;

   REveDigitSet(const REveDigitSet&);            // Not implemented
   REveDigitSet& operator=(const REveDigitSet&); // Not implemented

public:
   enum ERenderMode_e { kRM_AsIs, kRM_Line, kRM_Fill };

   typedef void (*Callback_foo)(REveDigitSet*, Int_t, TObject*);
   typedef TString (*TooltipCB_foo)(REveDigitSet*, Int_t);

   struct DigitBase_t
   {
      // Base-class for digit representation classes.

      Int_t  fValue;    // signal value of a digit (can be direct RGBA color)
      void  *fUserData{nullptr}; // user-data for given digit

      DigitBase_t(Int_t v=0) : fValue(v), fUserData(0) {}
   };

protected:
   TRefArray        *fDigitIds;       //  Array holding references to external objects.

   Int_t             fDefaultValue;   //  Default signal value.
   Bool_t            fValueIsColor;   //  Interpret signal value as RGBA color.
   Bool_t            fSingleColor;    //  Use the same color for all digits.
   Bool_t            fAntiFlick;      // Make extra render pass to avoid flickering when quads are too small.
   Bool_t            fOwnIds;         //  Flag specifying if id-objects are owned by the REveDigitSet.
   REveChunkManager  fPlex;           //  Container of digit data.
   DigitBase_t*      fLastDigit;      //! The last / current digit added to collection.
   Int_t             fLastIdx;        //! The last / current idx added to collection.

   Color_t           fColor;          //  Color used for frame (or all digis with single-color).
   REveFrameBox*     fFrame;          //  Pointer to frame structure.
   REveRGBAPalette*  fPalette;        //  Pointer to signal-color palette.
   ERenderMode_e     fRenderMode;     //  Render mode: as-is / line / filled.
   Bool_t            fSelectViaFrame; //  Allow selection via frame.
   Bool_t            fHighlightFrame; //  Highlight frame when object is selected.
   Bool_t            fDisableLighting;//  Disable lighting for rendering.
   Bool_t            fHistoButtons;   //  Show histogram buttons in object editor.

   Bool_t            fEmitSignals;    //  Emit signals on secondary-select.
   Callback_foo      fCallbackFoo;    //! Additional function to call on secondary-select.
   TooltipCB_foo     fTooltipCBFoo;   //! Function providing highlight tooltips when always-sec-select is active.

   DigitBase_t* NewDigit();
   void         ReleaseIds();

public:
   REveDigitSet(const char* n="REveDigitSet", const char* t="");
   virtual ~REveDigitSet();

   void   UseSingleColor();

   Bool_t GetAntiFlick() const   { return fAntiFlick; }
   void   SetAntiFlick(Bool_t f) { fAntiFlick = f; }

   virtual void SetMainColor(Color_t color) override;

   /*
   virtual void UnSelected();
   virtual void UnHighlighted();

   using REveElement::GetHighlightTooltip;
   virtual TString GetHighlightTooltip();
   */

   // Implemented in sub-classes:
   // virtual void Reset(EQuadType_e quadType, Bool_t valIsCol, Int_t chunkSize);

   void RefitPlex();
   void ScanMinMaxValues(Int_t& min, Int_t& max);

   // --------------------------------

   void SetCurrentDigit(Int_t idx);

   void DigitValue(Int_t value);
   void DigitColor(Color_t ci);
   void DigitColor(Color_t ci, Char_t transparency);
   void DigitColor(UChar_t r, UChar_t g, UChar_t b, UChar_t a=255);
   void DigitColor(UChar_t* rgba);

   Bool_t GetOwnIds() const     { return fOwnIds; }
   void   SetOwnIds(Bool_t o)   { fOwnIds = o; }

   void   DigitId(TObject* id);
   void   DigitUserData(void* ud);

   void   DigitId(Int_t n, TObject* id);
   void   DigitUserData(Int_t n, void* ud);

   DigitBase_t* GetDigit(Int_t n) const { return (DigitBase_t*) fPlex.Atom(n); }
   TObject*     GetId(Int_t n) const;
   void*        GetUserData(Int_t n) const;
   using REveElement::GetUserData;

   // --------------------------------

   // Implemented in subclasses:
   // virtual void ComputeBBox();
   /*
   virtual void Paint(Option_t* option="");

   virtual void DigitSelected(Int_t idx);
   virtual void SecSelected(REveDigitSet* qs, Int_t idx); // *SIGNAL*
   */
   // --------------------------------

   REveChunkManager* GetPlex() { return &fPlex; }

   REveFrameBox* GetFrame() const { return fFrame; }
   void          SetFrame(REveFrameBox* b);

   Bool_t GetSelectViaFrame() const    { return fSelectViaFrame; }
   void   SetSelectViaFrame(Bool_t sf) { fSelectViaFrame = sf; }

   Bool_t GetHighlightFrame() const    { return fHighlightFrame; }
   void   SetHighlightFrame(Bool_t hf) { fHighlightFrame = hf; }

   Bool_t GetValueIsColor()  const { return fValueIsColor; }

   REveRGBAPalette* GetPalette() const { return fPalette; }
   void             SetPalette(REveRGBAPalette* p);
   REveRGBAPalette* AssertPalette();

   ERenderMode_e  GetRenderMode()           const { return fRenderMode; }
   void           SetRenderMode(ERenderMode_e rm) { fRenderMode = rm; }

   Bool_t GetDisableLighting() const   { return fDisableLighting; }
   void   SetDisableLighting(Bool_t l) { fDisableLighting = l; }

   Bool_t GetHistoButtons() const   { return fHistoButtons; }
   void   SetHistoButtons(Bool_t f) { fHistoButtons = f; }

   Bool_t GetEmitSignals() const   { return fEmitSignals; }
   void   SetEmitSignals(Bool_t f) { fEmitSignals = f; }

   Callback_foo GetCallbackFoo()         const { return fCallbackFoo; }
   void         SetCallbackFoo(Callback_foo f) { fCallbackFoo = f; }

   TooltipCB_foo GetTooltipCBFoo()          const { return fTooltipCBFoo; }
   void          SetTooltipCBFoo(TooltipCB_foo f) { fTooltipCBFoo = f; }

   Int_t WriteCoreJson(nlohmann::json &j, Int_t rnr_offset) override;
};

} // namespace Experimental
} // namespace ROOT
#endif
<|endoftext|>