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

#include "GlCanvas.h"

#include <GteVector.h>
#include <absl/base/casts.h>
#include <glad/glad.h>
#include <math.h>

#include "AccessibleInterfaceProvider.h"
#include "App.h"
#include "CaptureWindow.h"
#include "GlUtils.h"
#include "ImGuiOrbit.h"
#include "Introspection/Introspection.h"
#include "IntrospectionWindow.h"
#include "OrbitAccessibility/AccessibleWidgetBridge.h"
#include "OrbitBase/Logging.h"

// TODO(b/227341686) z-values should not be of `float` type. E.g. make them `uint`.
// Tracks: 0.0 - 0.1
// Tracks - Moving: 0.1 - 0.2
// Tracks - Pinned: 0.2 - 0.3
// TimeBar: 0.3 - 0.4
// World Overlay: 0.4 - 0.5
// UI: 0.6 - 0.7
// ScreenSpace: 0.8 - 0.9
float GlCanvas::kZValueTrack = 0.01f;
float GlCanvas::kZValueIncompleteDataOverlayPicking = 0.02f;
float GlCanvas::kZValueEventBar = 0.03f;
float GlCanvas::kZValueBox = 0.05f;
float GlCanvas::kZValueBoxBorder = 0.06f;
float GlCanvas::kZValueEvent = 0.07f;
float GlCanvas::kZValueTrackText = 0.08f;
float GlCanvas::kZValueTrackLabel = 0.09f;
float GlCanvas::kZValueTimeBar = 0.31f;
float GlCanvas::kZValueTimeBarLabel = 0.33f;
float GlCanvas::kZValueTimeBarMouseLabel = 0.35f;
float GlCanvas::kZValueIncompleteDataOverlay = 0.42f;
float GlCanvas::kZValueOverlay = 0.43f;
float GlCanvas::kZValueOverlayLabel = 0.45f;
float GlCanvas::kZValueEventBarPicking = 0.49f;
float GlCanvas::kZValueUi = 0.61f;
float GlCanvas::kZValueMargin = 0.85f;
float GlCanvas::kZValueButtonBg = 0.87f;
float GlCanvas::kZValueButton = 0.89f;

float GlCanvas::kZOffsetMovingTrack = 0.1f;
float GlCanvas::kZOffsetPinnedTrack = 0.2f;

constexpr unsigned kNumberOriginalLayers = 17;
constexpr unsigned kExtraLayersForMovingTracks = 6;
constexpr unsigned kExtraLayersForPinnedTracks = 6;
constexpr unsigned kExtraLayersForSliderEpsilons = 4;
unsigned GlCanvas::kMaxNumberRealZLayers = kNumberOriginalLayers + kExtraLayersForMovingTracks +
                                           kExtraLayersForPinnedTracks +
                                           kExtraLayersForSliderEpsilons;

const Color GlCanvas::kBackgroundColor = Color(67, 67, 67, 255);
const Color GlCanvas::kTimeBarBackgroundColor = Color(33, 32, 33, 255);
const Color GlCanvas::kTabTextColorSelected = Color(100, 181, 246, 255);

GlCanvas::GlCanvas()
    : AccessibleInterfaceProvider(),
      viewport_(0, 0),
      ui_batcher_(BatcherId::kUi),
      primitive_assembler_(&ui_batcher_, &picking_manager_) {
  // Note that `GlCanvas` is the bridge to OpenGl content, and `GlCanvas`'s parent needs special
  // handling for accessibility. Thus, we use `nullptr` here.
  text_renderer_.SetViewport(&viewport_);

  is_selecting_ = false;
  double_clicking_ = false;
  control_key_ = false;
  redraw_requested_ = true;

  ref_time_click_ = 0.0;

  delta_time_ = 0.0f;

  hover_delay_ms_ = 300;
  ResetHoverTimer();
}

GlCanvas::~GlCanvas() {
  if (imgui_context_ != nullptr) {
    Orbit_ImGui_Shutdown();
    ImGui::DestroyContext();
  }
}

std::unique_ptr<GlCanvas> GlCanvas::Create(CanvasType canvas_type, OrbitApp* app) {
  switch (canvas_type) {
    case CanvasType::kCaptureWindow: {
      auto main_capture_window = std::make_unique<CaptureWindow>(app);
      app->SetCaptureWindow(main_capture_window.get());
      return main_capture_window;
    }
    case CanvasType::kIntrospectionWindow: {
      auto introspection_window = std::make_unique<IntrospectionWindow>(app);
      app->SetIntrospectionWindow(introspection_window.get());
      return introspection_window;
    }
    case CanvasType::kDebug:
      return std::make_unique<GlCanvas>();
    default:
      ORBIT_UNREACHABLE();
  }
}

void GlCanvas::EnableImGui() {
  if (imgui_context_ == nullptr) {
    imgui_context_ = ImGui::CreateContext();
    constexpr uint32_t kImGuiFontSize = 12;
    Orbit_ImGui_Init(kImGuiFontSize);
  }
}

bool GlCanvas::IsRedrawNeeded() const {
  return redraw_requested_ ||
         (is_mouse_over_ && can_hover_ && hover_timer_.ElapsedMillis() > hover_delay_ms_) ||
         viewport_.IsDirty();
}

void GlCanvas::MouseMoved(int x, int y, bool left, bool /*right*/, bool /*middle*/) {
  mouse_move_pos_screen_ = Vec2i(x, y);
  Vec2 mouse_pos_world = viewport_.ScreenToWorld(mouse_move_pos_screen_);

  if (left) {
    picking_manager_.Drag(x, y);
  }

  if (is_selecting_) {
    select_stop_pos_world_ = mouse_pos_world;
  }

  ResetHoverTimer();
  RequestRedraw();
}

void GlCanvas::LeftDown(int x, int y) {
  // Store world clicked pos for panning
  mouse_click_pos_world_ = viewport_.ScreenToWorld(Vec2i(x, y));
  SetPickingMode(PickingMode::kClick);
  is_selecting_ = false;

  Orbit_ImGui_MouseButtonCallback(imgui_context_, 0, true);

  RequestRedraw();
}

void GlCanvas::MouseWheelMoved(int x, int y, int delta, bool /*ctrl*/) {
  mouse_move_pos_screen_ = Vec2i(x, y);

  // Normalize and invert sign, so that delta < 0 is zoom in.
  int delta_normalized = delta < 0 ? 1 : -1;

  // Use the original sign of a_Delta here.
  Orbit_ImGui_ScrollCallback(imgui_context_, -delta_normalized);

  ResetHoverTimer();
  RequestRedraw();
}

void GlCanvas::LeftUp() {
  picking_manager_.Release();
  Orbit_ImGui_MouseButtonCallback(imgui_context_, 0, false);
  RequestRedraw();
}

void GlCanvas::LeftDoubleClick() {
  double_clicking_ = true;
  SetPickingMode(PickingMode::kClick);
  RequestRedraw();
}

void GlCanvas::RightDown(int x, int y) {
  mouse_click_pos_world_ = viewport_.ScreenToWorld(Vec2i(x, y));

  select_start_pos_world_ = select_stop_pos_world_ = mouse_click_pos_world_;
  is_selecting_ = true;
  SetPickingMode(PickingMode::kClick);

  Orbit_ImGui_MouseButtonCallback(imgui_context_, 1, true);
  RequestRedraw();
}

bool GlCanvas::RightUp() {
  Orbit_ImGui_MouseButtonCallback(imgui_context_, 1, false);
  is_selecting_ = false;
  RequestRedraw();

  bool show_context_menu = select_start_pos_world_ == select_stop_pos_world_;
  return show_context_menu;
}

void GlCanvas::CharEvent(unsigned int character) {
  Orbit_ImGui_CharCallback(imgui_context_, character);
  RequestRedraw();
}

void GlCanvas::KeyPressed(unsigned int key_code, bool ctrl, bool shift, bool alt) {
  UpdateSpecialKeys(ctrl, shift, alt);
  Orbit_ImGui_KeyCallback(imgui_context_, static_cast<int>(key_code), true, ctrl, shift, alt);
  RequestRedraw();
}

void GlCanvas::KeyReleased(unsigned int key_code, bool ctrl, bool shift, bool alt) {<commit_msg>Don't pick when right-clicking in TimeGraph [RELEASE] (#3741)<commit_after>// Copyright (c) 2020 The Orbit Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "GlCanvas.h"

#include <GteVector.h>
#include <absl/base/casts.h>
#include <glad/glad.h>
#include <math.h>

#include "AccessibleInterfaceProvider.h"
#include "App.h"
#include "CaptureWindow.h"
#include "GlUtils.h"
#include "ImGuiOrbit.h"
#include "Introspection/Introspection.h"
#include "IntrospectionWindow.h"
#include "OrbitAccessibility/AccessibleWidgetBridge.h"
#include "OrbitBase/Logging.h"

// TODO(b/227341686) z-values should not be of `float` type. E.g. make them `uint`.
// Tracks: 0.0 - 0.1
// Tracks - Moving: 0.1 - 0.2
// Tracks - Pinned: 0.2 - 0.3
// TimeBar: 0.3 - 0.4
// World Overlay: 0.4 - 0.5
// UI: 0.6 - 0.7
// ScreenSpace: 0.8 - 0.9
float GlCanvas::kZValueTrack = 0.01f;
float GlCanvas::kZValueIncompleteDataOverlayPicking = 0.02f;
float GlCanvas::kZValueEventBar = 0.03f;
float GlCanvas::kZValueBox = 0.05f;
float GlCanvas::kZValueBoxBorder = 0.06f;
float GlCanvas::kZValueEvent = 0.07f;
float GlCanvas::kZValueTrackText = 0.08f;
float GlCanvas::kZValueTrackLabel = 0.09f;
float GlCanvas::kZValueTimeBar = 0.31f;
float GlCanvas::kZValueTimeBarLabel = 0.33f;
float GlCanvas::kZValueTimeBarMouseLabel = 0.35f;
float GlCanvas::kZValueIncompleteDataOverlay = 0.42f;
float GlCanvas::kZValueOverlay = 0.43f;
float GlCanvas::kZValueOverlayLabel = 0.45f;
float GlCanvas::kZValueEventBarPicking = 0.49f;
float GlCanvas::kZValueUi = 0.61f;
float GlCanvas::kZValueMargin = 0.85f;
float GlCanvas::kZValueButtonBg = 0.87f;
float GlCanvas::kZValueButton = 0.89f;

float GlCanvas::kZOffsetMovingTrack = 0.1f;
float GlCanvas::kZOffsetPinnedTrack = 0.2f;

constexpr unsigned kNumberOriginalLayers = 17;
constexpr unsigned kExtraLayersForMovingTracks = 6;
constexpr unsigned kExtraLayersForPinnedTracks = 6;
constexpr unsigned kExtraLayersForSliderEpsilons = 4;
unsigned GlCanvas::kMaxNumberRealZLayers = kNumberOriginalLayers + kExtraLayersForMovingTracks +
                                           kExtraLayersForPinnedTracks +
                                           kExtraLayersForSliderEpsilons;

const Color GlCanvas::kBackgroundColor = Color(67, 67, 67, 255);
const Color GlCanvas::kTimeBarBackgroundColor = Color(33, 32, 33, 255);
const Color GlCanvas::kTabTextColorSelected = Color(100, 181, 246, 255);

GlCanvas::GlCanvas()
    : AccessibleInterfaceProvider(),
      viewport_(0, 0),
      ui_batcher_(BatcherId::kUi),
      primitive_assembler_(&ui_batcher_, &picking_manager_) {
  // Note that `GlCanvas` is the bridge to OpenGl content, and `GlCanvas`'s parent needs special
  // handling for accessibility. Thus, we use `nullptr` here.
  text_renderer_.SetViewport(&viewport_);

  is_selecting_ = false;
  double_clicking_ = false;
  control_key_ = false;
  redraw_requested_ = true;

  ref_time_click_ = 0.0;

  delta_time_ = 0.0f;

  hover_delay_ms_ = 300;
  ResetHoverTimer();
}

GlCanvas::~GlCanvas() {
  if (imgui_context_ != nullptr) {
    Orbit_ImGui_Shutdown();
    ImGui::DestroyContext();
  }
}

std::unique_ptr<GlCanvas> GlCanvas::Create(CanvasType canvas_type, OrbitApp* app) {
  switch (canvas_type) {
    case CanvasType::kCaptureWindow: {
      auto main_capture_window = std::make_unique<CaptureWindow>(app);
      app->SetCaptureWindow(main_capture_window.get());
      return main_capture_window;
    }
    case CanvasType::kIntrospectionWindow: {
      auto introspection_window = std::make_unique<IntrospectionWindow>(app);
      app->SetIntrospectionWindow(introspection_window.get());
      return introspection_window;
    }
    case CanvasType::kDebug:
      return std::make_unique<GlCanvas>();
    default:
      ORBIT_UNREACHABLE();
  }
}

void GlCanvas::EnableImGui() {
  if (imgui_context_ == nullptr) {
    imgui_context_ = ImGui::CreateContext();
    constexpr uint32_t kImGuiFontSize = 12;
    Orbit_ImGui_Init(kImGuiFontSize);
  }
}

bool GlCanvas::IsRedrawNeeded() const {
  return redraw_requested_ ||
         (is_mouse_over_ && can_hover_ && hover_timer_.ElapsedMillis() > hover_delay_ms_) ||
         viewport_.IsDirty();
}

void GlCanvas::MouseMoved(int x, int y, bool left, bool /*right*/, bool /*middle*/) {
  mouse_move_pos_screen_ = Vec2i(x, y);
  Vec2 mouse_pos_world = viewport_.ScreenToWorld(mouse_move_pos_screen_);

  if (left) {
    picking_manager_.Drag(x, y);
  }

  if (is_selecting_) {
    select_stop_pos_world_ = mouse_pos_world;
  }

  ResetHoverTimer();
  RequestRedraw();
}

void GlCanvas::LeftDown(int x, int y) {
  // Store world clicked pos for panning
  mouse_click_pos_world_ = viewport_.ScreenToWorld(Vec2i(x, y));
  SetPickingMode(PickingMode::kClick);
  is_selecting_ = false;

  Orbit_ImGui_MouseButtonCallback(imgui_context_, 0, true);

  RequestRedraw();
}

void GlCanvas::MouseWheelMoved(int x, int y, int delta, bool /*ctrl*/) {
  mouse_move_pos_screen_ = Vec2i(x, y);

  // Normalize and invert sign, so that delta < 0 is zoom in.
  int delta_normalized = delta < 0 ? 1 : -1;

  // Use the original sign of a_Delta here.
  Orbit_ImGui_ScrollCallback(imgui_context_, -delta_normalized);

  ResetHoverTimer();
  RequestRedraw();
}

void GlCanvas::LeftUp() {
  picking_manager_.Release();
  Orbit_ImGui_MouseButtonCallback(imgui_context_, 0, false);
  RequestRedraw();
}

void GlCanvas::LeftDoubleClick() {
  double_clicking_ = true;
  SetPickingMode(PickingMode::kClick);
  RequestRedraw();
}

void GlCanvas::RightDown(int x, int y) {
  mouse_click_pos_world_ = viewport_.ScreenToWorld(Vec2i(x, y));

  select_start_pos_world_ = select_stop_pos_world_ = mouse_click_pos_world_;
  is_selecting_ = true;

  Orbit_ImGui_MouseButtonCallback(imgui_context_, 1, true);
  RequestRedraw();
}

bool GlCanvas::RightUp() {
  Orbit_ImGui_MouseButtonCallback(imgui_context_, 1, false);
  is_selecting_ = false;
  RequestRedraw();

  bool show_context_menu = select_start_pos_world_ == select_stop_pos_world_;
  return show_context_menu;
}

void GlCanvas::CharEvent(unsigned int character) {
  Orbit_ImGui_CharCallback(imgui_context_, character);
  RequestRedraw();
}

void GlCanvas::KeyPressed(unsigned int key_code, bool ctrl, bool shift, bool alt) {
  UpdateSpecialKeys(ctrl, shift, alt);
  Orbit_ImGui_KeyCallback(imgui_context_, static_cast<int>(key_code), true, ctrl, shift, alt);
  RequestRedraw();
}

void GlCanvas::KeyReleased(unsigned int key_code, bool ctrl, bool shift, bool alt) {
{'fraction_non_alphanumeric': 0.11500421682128345, 'fraction_numerical': 0.025300927700682357, 'mean_word_length': 4.787045252883762, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2232631', 'n_tokens_mistral': 4811, 'n_tokens_neox': 4550, 'n_words': 948}